diff options
Diffstat (limited to 'src/qml/qml/v8')
58 files changed, 2005 insertions, 12508 deletions
diff --git a/src/qml/qml/v8/qjsconverter_impl_p.h b/src/qml/qml/v8/qjsconverter_impl_p.h deleted file mode 100644 index 4b17d5ed31..0000000000 --- a/src/qml/qml/v8/qjsconverter_impl_p.h +++ /dev/null @@ -1,273 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qjsconverter_p.h" -#include <stdlib.h> - -#ifndef QJSCONVERTER_IMPL_P_H -#define QJSCONVERTER_IMPL_P_H - -#ifdef Q_OS_QNX -#include <malloc.h> -#endif - -QT_BEGIN_NAMESPACE - -extern char *qdtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve, char **digits_str); -Q_CORE_EXPORT QString qt_regexp_toCanonical(const QString &, QRegExp::PatternSyntax); - - -quint32 QJSConverter::toArrayIndex(const QString& string) -{ - // FIXME this function should be exported by JSC C API. - bool ok; - quint32 idx = string.toUInt(&ok); - if (!ok || toString(idx) != string) - idx = 0xffffffff; - - return idx; -} - -QString QJSConverter::toString(v8::Handle<v8::String> jsString) -{ - if (jsString.IsEmpty()) - return QString(); - QString qstr; - qstr.resize(jsString->Length()); - jsString->Write(reinterpret_cast<uint16_t*>(qstr.data())); - return qstr; -} - -v8::Local<v8::String> QJSConverter::toString(const QString& string) -{ - return v8::String::New(reinterpret_cast<const uint16_t*>(string.data()), string.size()); -} - -QString QJSConverter::toString(double value) -{ - // FIXME this should be easier. The ideal fix is to create - // a new function in V8 API which could cover the functionality. - - if (qIsNaN(value)) - return QString::fromLatin1("NaN"); - if (qIsInf(value)) - return QString::fromLatin1(value < 0 ? "-Infinity" : "Infinity"); - if (!value) - return QString::fromLatin1("0"); - - QVarLengthArray<char, 25> buf; - int decpt; - int sign; - char* result = 0; - char* endresult; - (void)qdtoa(value, 0, 0, &decpt, &sign, &endresult, &result); - - if (!result) - return QString(); - - int resultLen = endresult - result; - if (decpt <= 0 && decpt > -6) { - buf.resize(-decpt + 2 + sign); - memset(buf.data(), '0', -decpt + 2 + sign); - if (sign) // fix the sign. - buf[0] = '-'; - buf[sign + 1] = '.'; - buf.append(result, resultLen); - } else { - if (sign) - buf.append('-'); - int length = buf.size() - sign + resultLen; - if (decpt <= 21 && decpt > 0) { - if (length <= decpt) { - const char* zeros = "0000000000000000000000000"; - buf.append(result, resultLen); - buf.append(zeros, decpt - length); - } else { - buf.append(result, decpt); - buf.append('.'); - buf.append(result + decpt, resultLen - decpt); - } - } else if (result[0] >= '0' && result[0] <= '9') { - if (length > 1) { - buf.append(result, 1); - buf.append('.'); - buf.append(result + 1, resultLen - 1); - } else - buf.append(result, resultLen); - buf.append('e'); - buf.append(decpt >= 0 ? '+' : '-'); - int e = qAbs(decpt - 1); - if (e >= 100) - buf.append('0' + e / 100); - if (e >= 10) - buf.append('0' + (e % 100) / 10); - buf.append('0' + e % 10); - } - } - free(result); - buf.append(0); - return QString::fromLatin1(buf.constData()); -} - -// return a mask of v8::PropertyAttribute that may also contains QScriptValue::PropertyGetter or QScriptValue::PropertySetter -uint QJSConverter::toPropertyAttributes(const QFlags<QJSValuePrivate::PropertyFlag>& flags) -{ - uint attr = 0; - if (flags.testFlag(QJSValuePrivate::ReadOnly)) - attr |= v8::ReadOnly; - if (flags.testFlag(QJSValuePrivate::Undeletable)) - attr |= v8::DontDelete; - if (flags.testFlag(QJSValuePrivate::SkipInEnumeration)) - attr |= v8::DontEnum; - // if (flags.testFlag(QScriptValue::PropertyGetter)) - // attr |= QScriptValue::PropertyGetter; - // if (flags.testFlag(QScriptValue::PropertySetter)) - // attr |= QScriptValue::PropertySetter; - return attr; -} - -// Converts a JS RegExp to a QRegExp. -// The conversion is not 100% exact since ECMA regexp and QRegExp -// have different semantics/flags, but we try to do our best. -QRegExp QJSConverter::toRegExp(v8::Handle<v8::RegExp> jsRegExp) -{ - QString pattern = QJSConverter::toString(jsRegExp->GetSource()); - Qt::CaseSensitivity caseSensitivity = Qt::CaseSensitive; - if (jsRegExp->GetFlags() & v8::RegExp::kIgnoreCase) - caseSensitivity = Qt::CaseInsensitive; - return QRegExp(pattern, caseSensitivity, QRegExp::RegExp2); -} - -// Converts a QRegExp to a JS RegExp. -// The conversion is not 100% exact since ECMA regexp and QRegExp -// have different semantics/flags, but we try to do our best. -v8::Local<v8::RegExp> QJSConverter::toRegExp(const QRegExp &re) -{ - // Convert the pattern to a ECMAScript pattern. - QString pattern = qt_regexp_toCanonical(re.pattern(), re.patternSyntax()); - if (re.isMinimal()) { - QString ecmaPattern; - int len = pattern.length(); - ecmaPattern.reserve(len); - int i = 0; - const QChar *wc = pattern.unicode(); - bool inBracket = false; - while (i < len) { - QChar c = wc[i++]; - ecmaPattern += c; - switch (c.unicode()) { - case '?': - case '+': - case '*': - case '}': - if (!inBracket) - ecmaPattern += QLatin1Char('?'); - break; - case '\\': - if (i < len) - ecmaPattern += wc[i++]; - break; - case '[': - inBracket = true; - break; - case ']': - inBracket = false; - break; - default: - break; - } - } - pattern = ecmaPattern; - } - - int flags = v8::RegExp::kNone; - if (re.caseSensitivity() == Qt::CaseInsensitive) - flags |= v8::RegExp::kIgnoreCase; - - return v8::RegExp::New(QJSConverter::toString(pattern), static_cast<v8::RegExp::Flags>(flags)); -} - -// Converts a QStringList to JS. -// The result is a new Array object with length equal to the length -// of the QStringList, and the elements being the QStringList's -// elements converted to JS Strings. -v8::Local<v8::Array> QJSConverter::toStringList(const QStringList &lst) -{ - v8::Local<v8::Array> result = v8::Array::New(lst.size()); - for (int i = 0; i < lst.size(); ++i) - result->Set(i, toString(lst.at(i))); - return result; -} - -// Converts a JS Array object to a QStringList. -// The result is a QStringList with length equal to the length -// of the JS Array, and elements being the JS Array's elements -// converted to QStrings. -QStringList QJSConverter::toStringList(v8::Handle<v8::Array> jsArray) -{ - QStringList result; - uint32_t length = jsArray->Length(); - for (uint32_t i = 0; i < length; ++i) - result.append(toString(jsArray->Get(i)->ToString())); - return result; -} - - -// Converts a JS Date to a QDateTime. -QDateTime QJSConverter::toDateTime(v8::Handle<v8::Date> jsDate) -{ - return QDateTime::fromMSecsSinceEpoch(jsDate->NumberValue()); -} - -// Converts a QDateTime to a JS Date. -v8::Local<v8::Value> QJSConverter::toDateTime(const QDateTime &dt) -{ - double date; - if (!dt.isValid()) - date = qSNaN(); - else - date = dt.toMSecsSinceEpoch(); - return v8::Date::New(date); -} - -QT_END_NAMESPACE - -#endif // QJSCONVERTER_IMPL_P_H diff --git a/src/qml/qml/v8/qjsconverter_p.h b/src/qml/qml/v8/qjsconverter_p.h deleted file mode 100644 index 5f6633f580..0000000000 --- a/src/qml/qml/v8/qjsconverter_p.h +++ /dev/null @@ -1,111 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QJSCONVERTER_P_H -#define QJSCONVERTER_P_H - -#include "qjsvalue_p.h" -#include <QtCore/qglobal.h> -#include <QtCore/qnumeric.h> -#include <QtCore/qstring.h> -#include <QtCore/qstringlist.h> -#include <QtCore/qvarlengtharray.h> -#include <QtCore/qregexp.h> -#include <QtCore/qdatetime.h> - -#include <private/qv8_p.h> - -QT_BEGIN_NAMESPACE - -/* - \internal - \class QJSConverter - QJSValue and QJSEngine helper class. This class's responsibility is to convert values - between JS values and Qt/C++ values. - - This is a nice way to inline these functions in both QJSValue and QJSEngine. -*/ -class QJSConverter { -public: - static inline quint32 toArrayIndex(const QString& string); - - static inline QString toString(v8::Handle<v8::String> jsString); - static inline v8::Local<v8::String> toString(const QString& string); - static inline QString toString(double value); - - enum { - PropertyAttributeMask = v8::ReadOnly | v8::DontDelete | v8::DontEnum, - }; - // return a mask of v8::PropertyAttribute that may also contains QScriptValue::PropertyGetter or QScriptValue::PropertySetter - static inline uint toPropertyAttributes(const QFlags<QJSValuePrivate::PropertyFlag>& flags); - - // Converts a JS RegExp to a QRegExp. - // The conversion is not 100% exact since ECMA regexp and QRegExp - // have different semantics/flags, but we try to do our best. - static inline QRegExp toRegExp(v8::Handle<v8::RegExp> jsRegExp); - - // Converts a QRegExp to a JS RegExp. - // The conversion is not 100% exact since ECMA regexp and QRegExp - // have different semantics/flags, but we try to do our best. - static inline v8::Local<v8::RegExp> toRegExp(const QRegExp &re); - - // Converts a QStringList to JS. - // The result is a new Array object with length equal to the length - // of the QStringList, and the elements being the QStringList's - // elements converted to JS Strings. - static inline v8::Local<v8::Array> toStringList(const QStringList &lst); - - // Converts a JS Array object to a QStringList. - // The result is a QStringList with length equal to the length - // of the JS Array, and elements being the JS Array's elements - // converted to QStrings. - static inline QStringList toStringList(v8::Handle<v8::Array> jsArray); - - // Converts a JS Date to a QDateTime. - static inline QDateTime toDateTime(v8::Handle<v8::Date> jsDate); - - // Converts a QDateTime to a JS Date. - static inline v8::Local<v8::Value> toDateTime(const QDateTime &dt); -}; - -QT_END_NAMESPACE - -#endif diff --git a/src/qml/qml/v8/qjsengine.cpp b/src/qml/qml/v8/qjsengine.cpp index dbd0851fec..13281875e6 100644 --- a/src/qml/qml/v8/qjsengine.cpp +++ b/src/qml/qml/v8/qjsengine.cpp @@ -43,10 +43,13 @@ #include "qjsengine_p.h" #include "qjsvalue.h" #include "qjsvalue_p.h" -#include "qscriptisolate_p.h" -#include "qscript_impl_p.h" #include "qv8engine_p.h" +#include "private/qv4engine_p.h" +#include "private/qv4mm_p.h" +#include "private/qv4globalobject_p.h" +#include "private/qv4script_p.h" + #include <QtCore/qdatetime.h> #include <QtCore/qmetaobject.h> #include <QtCore/qstringlist.h> @@ -62,13 +65,13 @@ #include <qmutex.h> #include <qwaitcondition.h> #include <private/qqmlglobal_p.h> +#include <qqmlengine.h> #undef Q_D #undef Q_Q #define Q_D(blah) #define Q_Q(blah) -Q_DECLARE_METATYPE(QObjectList) Q_DECLARE_METATYPE(QList<int>) /*! @@ -223,9 +226,7 @@ QJSEngine::~QJSEngine() */ void QJSEngine::collectGarbage() { - Q_D(QJSEngine); - QScriptIsolate api(d); - d->collectGarbage(); + d->m_v4Engine->memoryManager->runGC(); } /*! @@ -258,10 +259,18 @@ void QJSEngine::collectGarbage() */ QJSValue QJSEngine::evaluate(const QString& program, const QString& fileName, int lineNumber) { - Q_D(QJSEngine); - QScriptIsolate api(d, QScriptIsolate::NotNullEngine); - v8::HandleScope handleScope; - return QJSValuePrivate::get(d->evaluate(program, fileName, qmlSourceCoordinate(lineNumber))); + QV4::ExecutionContext *ctx = d->m_v4Engine->current; + try { + QV4::Script script(ctx, program, fileName, lineNumber); + script.strictMode = ctx->strictMode; + script.inheritContext = true; + script.parse(); + QV4::Value result = script.run(); + return new QJSValuePrivate(d->m_v4Engine, result); + } catch (QV4::Exception& ex) { + ex.accept(ctx); + return new QJSValuePrivate(d->m_v4Engine, ex.value()); + } } /*! @@ -274,10 +283,7 @@ QJSValue QJSEngine::evaluate(const QString& program, const QString& fileName, in */ QJSValue QJSEngine::newObject() { - Q_D(QJSEngine); - QScriptIsolate api(d, QScriptIsolate::NotNullEngine); - v8::HandleScope handleScope; - return QJSValuePrivate::get(new QJSValuePrivate(d, v8::Object::New())); + return new QJSValuePrivate(d->m_v4Engine->newObject()); } /*! @@ -287,10 +293,11 @@ QJSValue QJSEngine::newObject() */ QJSValue QJSEngine::newArray(uint length) { - Q_D(QJSEngine); - QScriptIsolate api(d, QScriptIsolate::NotNullEngine); - v8::HandleScope handleScope; - return QJSValuePrivate::get(d->newArray(length)); + QV4::ArrayObject *array = d->m_v4Engine->newArrayObject(); + if (length < 0x1000) + array->arrayReserve(length); + array->setArrayLengthUnchecked(length); + return new QJSValuePrivate(array); } /*! @@ -316,9 +323,9 @@ QJSValue QJSEngine::newArray(uint length) QJSValue QJSEngine::newQObject(QObject *object) { Q_D(QJSEngine); - QScriptIsolate api(d, QScriptIsolate::NotNullEngine); - v8::HandleScope handleScope; - return d->scriptValueFromInternal(d->newQObject(object, QV8Engine::JavaScriptOwnership)); + QV4::ExecutionEngine *v4 = QV8Engine::getV4(d); + QQmlEngine::setObjectOwnership(object, QQmlEngine::JavaScriptOwnership); + return new QJSValuePrivate(v4, QV4::QObjectWrapper::wrap(v4, object)); } /*! @@ -333,10 +340,7 @@ QJSValue QJSEngine::newQObject(QObject *object) */ QJSValue QJSEngine::globalObject() const { - Q_D(const QJSEngine); - QScriptIsolate api(d, QScriptIsolate::NotNullEngine); - v8::HandleScope handleScope; - return d->scriptValueFromInternal(d->global()); + return new QJSValuePrivate(d->m_v4Engine->globalObject); } /*! @@ -346,9 +350,7 @@ QJSValue QJSEngine::globalObject() const QJSValue QJSEngine::create(int type, const void *ptr) { Q_D(QJSEngine); - QScriptIsolate api(d, QScriptIsolate::NotNullEngine); - v8::HandleScope handleScope; - return d->scriptValueFromInternal(d->metaTypeToJS(type, ptr)); + return new QJSValuePrivate(d->m_v4Engine, d->metaTypeToJS(type, ptr)); } /*! @@ -358,51 +360,49 @@ QJSValue QJSEngine::create(int type, const void *ptr) bool QJSEngine::convertV2(const QJSValue &value, int type, void *ptr) { QJSValuePrivate *vp = QJSValuePrivate::get(value); - QV8Engine *engine = vp->engine(); + QV8Engine *engine = vp->engine ? vp->engine->v8Engine : 0; if (engine) { - QScriptIsolate api(engine, QScriptIsolate::NotNullEngine); - v8::HandleScope handleScope; - return engine->metaTypeFromJS(*vp, type, ptr); + return engine->metaTypeFromJS(vp->getValue(engine->m_v4Engine), type, ptr); } else { switch (type) { case QMetaType::Bool: - *reinterpret_cast<bool*>(ptr) = vp->toBool(); + *reinterpret_cast<bool*>(ptr) = vp->value.toBoolean(); return true; case QMetaType::Int: - *reinterpret_cast<int*>(ptr) = vp->toInt32(); + *reinterpret_cast<int*>(ptr) = vp->value.toInt32(); return true; case QMetaType::UInt: - *reinterpret_cast<uint*>(ptr) = vp->toUInt32(); + *reinterpret_cast<uint*>(ptr) = vp->value.toUInt32(); return true; case QMetaType::LongLong: - *reinterpret_cast<qlonglong*>(ptr) = vp->toInteger(); + *reinterpret_cast<qlonglong*>(ptr) = vp->value.toInteger(); return true; case QMetaType::ULongLong: - *reinterpret_cast<qulonglong*>(ptr) = vp->toInteger(); + *reinterpret_cast<qulonglong*>(ptr) = vp->value.toInteger(); return true; case QMetaType::Double: - *reinterpret_cast<double*>(ptr) = vp->toNumber(); + *reinterpret_cast<double*>(ptr) = vp->value.toNumber(); return true; case QMetaType::QString: - *reinterpret_cast<QString*>(ptr) = vp->toString(); + *reinterpret_cast<QString*>(ptr) = value.toString(); return true; case QMetaType::Float: - *reinterpret_cast<float*>(ptr) = vp->toNumber(); + *reinterpret_cast<float*>(ptr) = vp->value.toNumber(); return true; case QMetaType::Short: - *reinterpret_cast<short*>(ptr) = vp->toInt32(); + *reinterpret_cast<short*>(ptr) = vp->value.toInt32(); return true; case QMetaType::UShort: - *reinterpret_cast<unsigned short*>(ptr) = vp->toUInt16(); + *reinterpret_cast<unsigned short*>(ptr) = vp->value.toUInt16(); return true; case QMetaType::Char: - *reinterpret_cast<char*>(ptr) = vp->toInt32(); + *reinterpret_cast<char*>(ptr) = vp->value.toInt32(); return true; case QMetaType::UChar: - *reinterpret_cast<unsigned char*>(ptr) = vp->toUInt16(); + *reinterpret_cast<unsigned char*>(ptr) = vp->value.toUInt16(); return true; case QMetaType::QChar: - *reinterpret_cast<QChar*>(ptr) = vp->toUInt16(); + *reinterpret_cast<QChar*>(ptr) = vp->value.toUInt16(); return true; default: return false; @@ -424,35 +424,6 @@ bool QJSEngine::convertV2(const QJSValue &value, int type, void *ptr) \sa toScriptValue() */ -/*! - \internal - - Returns this engine's internal V8 context. - - The context enables direct use of the V8 API. - The caller is responsible for ensuring that a handle scope is in place, - and for entering/exiting the context. - Example: - - \code - QJSEngine eng; - ... - v8::HandleScope handleScope; - v8::Local<v8::Context> context = qt_QJSEngineV8Context(&eng); - v8::Context::Scope contextScope(context); - - // Do stuff (e.g., call v8::Script::Compile()) ... - \endcode - - \sa qt_QJSValueV8Value() -*/ -Q_QML_EXPORT v8::Local<v8::Context> qt_QJSEngineV8Context(QJSEngine *engine) -{ - Q_ASSERT(engine != 0); - QV8Engine *d = engine->handle(); - return v8::Local<v8::Context>::New(d->context()); -} - QT_END_NAMESPACE #include "moc_qjsengine.cpp" diff --git a/src/qml/qml/v8/qjsvalue.cpp b/src/qml/qml/v8/qjsvalue.cpp index 87be773218..ffbc469a76 100644 --- a/src/qml/qml/v8/qjsvalue.cpp +++ b/src/qml/qml/v8/qjsvalue.cpp @@ -39,14 +39,41 @@ ** ****************************************************************************/ -#include "qscriptisolate_p.h" +#include <QtCore/qstring.h> +#include <QtCore/qvarlengtharray.h> +#include <QtCore/qdatetime.h> #include "qjsengine.h" -#include "qv8engine_p.h" #include "qjsvalue.h" #include "qjsvalue_p.h" -#include "qscript_impl_p.h" -#include "qscriptshareddata_p.h" -#include <QtCore/qstring.h> +#include "qv4value_p.h" +#include "qv4object_p.h" +#include "qv4functionobject_p.h" +#include "qv4dateobject_p.h" +#include "qv4runtime_p.h" +#include "qv4variantobject_p.h" +#include "qv4regexpobject_p.h" +#include "qv8engine_p.h" +#include <private/qv4mm_p.h> + +QV4::Value QJSValuePrivate::getValue(QV4::ExecutionEngine *e) +{ + if (!this->engine) + this->engine = e; + else if (this->engine != e) { + qWarning("JSValue can't be reassigned to another engine."); + return QV4::Value::emptyValue(); + } + if (value.asString() == &string) { + value = QV4::Value::fromString(engine->newString(string.toQString())); + PersistentValuePrivate **listRoot = &engine->memoryManager->m_persistentValues; + prev = listRoot; + next = *listRoot; + *prev = this; + if (next) + next->prev = &this->next; + } + return value; +} /*! \since 5.0 @@ -114,11 +141,18 @@ QT_BEGIN_NAMESPACE +using namespace QV4; + /*! Constructs a new QJSValue with a boolean \a value. */ QJSValue::QJSValue(bool value) - : d_ptr(new QJSValuePrivate(value)) + : d(new QJSValuePrivate(0, Value::fromBoolean(value))) +{ +} + +QJSValue::QJSValue(QJSValuePrivate *dd) + : d(dd) { } @@ -126,7 +160,7 @@ QJSValue::QJSValue(bool value) Constructs a new QJSValue with a number \a value. */ QJSValue::QJSValue(int value) - : d_ptr(new QJSValuePrivate(value)) + : d(new QJSValuePrivate(0, Value::fromInt32(value))) { } @@ -134,7 +168,7 @@ QJSValue::QJSValue(int value) Constructs a new QJSValue with a number \a value. */ QJSValue::QJSValue(uint value) - : d_ptr(new QJSValuePrivate(value)) + : d(new QJSValuePrivate(0, Value::fromUInt32(value))) { } @@ -142,7 +176,7 @@ QJSValue::QJSValue(uint value) Constructs a new QJSValue with a number \a value. */ QJSValue::QJSValue(double value) - : d_ptr(new QJSValuePrivate(value)) + : d(new QJSValuePrivate(0, Value::fromDouble(value))) { } @@ -150,7 +184,7 @@ QJSValue::QJSValue(double value) Constructs a new QJSValue with a string \a value. */ QJSValue::QJSValue(const QString& value) - : d_ptr(new QJSValuePrivate(value)) + : d(new QJSValuePrivate(value)) { } @@ -158,7 +192,7 @@ QJSValue::QJSValue(const QString& value) Constructs a new QJSValue with a special \a value. */ QJSValue::QJSValue(SpecialValue value) - : d_ptr(new QJSValuePrivate(value)) + : d(new QJSValuePrivate(0, value == UndefinedValue ? Value::undefinedValue() : Value::nullValue())) { } @@ -166,7 +200,7 @@ QJSValue::QJSValue(SpecialValue value) Constructs a new QJSValue with a string \a value. */ QJSValue::QJSValue(const QLatin1String &value) - : d_ptr(new QJSValuePrivate(value)) + : d(new QJSValuePrivate(value)) { } @@ -175,30 +209,12 @@ QJSValue::QJSValue(const QLatin1String &value) */ #ifndef QT_NO_CAST_FROM_ASCII QJSValue::QJSValue(const char *value) - : d_ptr(new QJSValuePrivate(QString::fromLatin1(value))) + : d(new QJSValuePrivate(QString::fromLatin1(value))) { } #endif /*! - Constructs a new QJSValue from private - \internal -*/ -QJSValue::QJSValue(QJSValuePrivate* d) - : d_ptr(d) -{ -} - -/*! - Constructs a new QJSValue from private - \internal -*/ -QJSValue::QJSValue(QScriptPassPointer<QJSValuePrivate> d) - : d_ptr(d.give()) -{ -} - -/*! Constructs a new QJSValue that is a copy of \a other. Note that if \a other is an object (i.e., isObject() would return @@ -206,8 +222,9 @@ QJSValue::QJSValue(QScriptPassPointer<QJSValuePrivate> d) the new script value (i.e., the object itself is not copied). */ QJSValue::QJSValue(const QJSValue& other) - : d_ptr(other.d_ptr) + : d(other.d) { + d->ref(); } /*! @@ -215,6 +232,7 @@ QJSValue::QJSValue(const QJSValue& other) */ QJSValue::~QJSValue() { + d->deref(); } /*! @@ -225,9 +243,7 @@ QJSValue::~QJSValue() */ bool QJSValue::isBool() const { - Q_D(const QJSValue); - QScriptIsolate api(d->engine()); - return d->isBool(); + return d->value.isBoolean(); } /*! @@ -238,9 +254,7 @@ bool QJSValue::isBool() const */ bool QJSValue::isNumber() const { - Q_D(const QJSValue); - QScriptIsolate api(d->engine()); - return d->isNumber(); + return d->value.isNumber(); } /*! @@ -249,9 +263,7 @@ bool QJSValue::isNumber() const */ bool QJSValue::isNull() const { - Q_D(const QJSValue); - QScriptIsolate api(d->engine()); - return d->isNull(); + return d->value.isNull(); } /*! @@ -262,9 +274,7 @@ bool QJSValue::isNull() const */ bool QJSValue::isString() const { - Q_D(const QJSValue); - QScriptIsolate api(d->engine()); - return d->isString(); + return d->value.isString(); } /*! @@ -273,9 +283,7 @@ bool QJSValue::isString() const */ bool QJSValue::isUndefined() const { - Q_D(const QJSValue); - QScriptIsolate api(d->engine()); - return d->isUndefined(); + return d->value.isUndefined(); } /*! @@ -284,9 +292,8 @@ bool QJSValue::isUndefined() const */ bool QJSValue::isError() const { - Q_D(const QJSValue); - QScriptIsolate api(d->engine()); - return d->isError(); + Object *o = d->value.asObject(); + return o && o->asErrorObject(); } /*! @@ -297,10 +304,8 @@ bool QJSValue::isError() const */ bool QJSValue::isArray() const { - Q_D(const QJSValue); - QScriptIsolate api(d->engine()); - return d->isArray(); - } + return d->value.asArrayObject(); +} /*! Returns true if this QJSValue is of the Object type; otherwise @@ -313,9 +318,7 @@ bool QJSValue::isArray() const */ bool QJSValue::isObject() const { - Q_D(const QJSValue); - QScriptIsolate api(d->engine()); - return d->isObject(); + return d->value.asObject(); } /*! @@ -326,9 +329,7 @@ bool QJSValue::isObject() const */ bool QJSValue::isCallable() const { - Q_D(const QJSValue); - QScriptIsolate api(d->engine()); - return d->isCallable(); + return d->value.asFunctionObject(); } /*! @@ -339,9 +340,8 @@ bool QJSValue::isCallable() const */ bool QJSValue::isVariant() const { - Q_D(const QJSValue); - QScriptIsolate api(d->engine()); - return d->isVariant(); + Managed *m = d->value.asManaged(); + return m ? m->as<QV4::VariantObject>() : 0; } /*! @@ -358,9 +358,7 @@ bool QJSValue::isVariant() const */ QString QJSValue::toString() const { - Q_D(const QJSValue); - QScriptIsolate api(d->engine()); - return d->toString(); + return d->value.toQString(); } /*! @@ -377,9 +375,13 @@ QString QJSValue::toString() const */ double QJSValue::toNumber() const { - Q_D(const QJSValue); - QScriptIsolate api(d->engine()); - return d->toNumber(); + QV4::ExecutionContext *ctx = d->engine ? d->engine->current : 0; + try { + return d->value.toNumber(); + } catch (Exception &e) { + e.accept(ctx); + return 0; + } } /*! @@ -396,9 +398,13 @@ double QJSValue::toNumber() const */ bool QJSValue::toBool() const { - Q_D(const QJSValue); - QScriptIsolate api(d->engine()); - return d->toBool(); + QV4::ExecutionContext *ctx = d->engine ? d->engine->current : 0; + try { + return d->value.toBoolean(); + } catch (Exception &e) { + e.accept(ctx); + return false; + } } /*! @@ -415,9 +421,13 @@ bool QJSValue::toBool() const */ qint32 QJSValue::toInt() const { - Q_D(const QJSValue); - QScriptIsolate api(d->engine()); - return d->toInt32(); + QV4::ExecutionContext *ctx = d->engine ? d->engine->current : 0; + try { + return d->value.toInt32(); + } catch (Exception &e) { + e.accept(ctx); + return 0; + } } /*! @@ -434,9 +444,13 @@ qint32 QJSValue::toInt() const */ quint32 QJSValue::toUInt() const { - Q_D(const QJSValue); - QScriptIsolate api(d->engine()); - return d->toUInt32(); + QV4::ExecutionContext *ctx = d->engine ? d->engine->current : 0; + try { + return d->value.toUInt32(); + } catch (Exception &e) { + e.accept(ctx); + return 0; + } } /*! @@ -463,9 +477,7 @@ quint32 QJSValue::toUInt() const */ QVariant QJSValue::toVariant() const { - Q_D(const QJSValue); - QScriptIsolate api(d->engine()); - return d->toVariant(); + return QV4::VariantObject::toVariant(d->value); } /*! @@ -485,9 +497,32 @@ QVariant QJSValue::toVariant() const */ QJSValue QJSValue::call(const QJSValueList &args) { - Q_D(QJSValue); - QScriptIsolate api(d->engine()); - return d->call(/*thisObject=*/0, args); + FunctionObject *f = d->value.asFunctionObject(); + if (!f) + return QJSValue(); + + ExecutionEngine *engine = d->engine; + assert(engine); + + QVarLengthArray<Value, 9> arguments(args.length()); + for (int i = 0; i < args.size(); ++i) { + if (!args.at(i).d->checkEngine(engine)) { + qWarning("QJSValue::call() failed: cannot call function with argument created in a different engine"); + return QJSValue(); + } + arguments[i] = args.at(i).d->getValue(engine); + } + + Value result; + QV4::ExecutionContext *ctx = engine->current; + try { + result = f->call(Value::fromObject(engine->globalObject), arguments.data(), arguments.size()); + } catch (Exception &e) { + e.accept(ctx); + result = e.value(); + } + + return new QJSValuePrivate(engine, result); } /*! @@ -512,9 +547,37 @@ QJSValue QJSValue::call(const QJSValueList &args) */ QJSValue QJSValue::callWithInstance(const QJSValue &instance, const QJSValueList &args) { - Q_D(QJSValue); - QScriptIsolate api(d->engine()); - return d->call(QJSValuePrivate::get(instance), args); + FunctionObject *f = d->value.asFunctionObject(); + if (!f) + return QJSValue(); + + ExecutionEngine *engine = d->engine; + assert(engine); + + if (!instance.d->checkEngine(engine)) { + qWarning("QJSValue::call() failed: cannot call function with thisObject created in a different engine"); + return QJSValue(); + } + + QVarLengthArray<Value, 9> arguments(args.length()); + for (int i = 0; i < args.size(); ++i) { + if (!args.at(i).d->checkEngine(engine)) { + qWarning("QJSValue::call() failed: cannot call function with argument created in a different engine"); + return QJSValue(); + } + arguments[i] = args.at(i).d->getValue(engine); + } + + Value result; + QV4::ExecutionContext *ctx = engine->current; + try { + result = f->call(instance.d->getValue(engine), arguments.data(), arguments.size()); + } catch (Exception &e) { + e.accept(ctx); + result = e.value(); + } + + return new QJSValuePrivate(engine, result); } /*! @@ -537,9 +600,32 @@ QJSValue QJSValue::callWithInstance(const QJSValue &instance, const QJSValueList */ QJSValue QJSValue::callAsConstructor(const QJSValueList &args) { - Q_D(QJSValue); - QScriptIsolate api(d->engine()); - return QJSValuePrivate::get(d->callAsConstructor(args)); + FunctionObject *f = d->value.asFunctionObject(); + if (!f) + return QJSValue(); + + ExecutionEngine *engine = d->engine; + assert(engine); + + QVarLengthArray<Value, 9> arguments(args.length()); + for (int i = 0; i < args.size(); ++i) { + if (!args.at(i).d->checkEngine(engine)) { + qWarning("QJSValue::callAsConstructor() failed: cannot construct function with argument created in a different engine"); + return QJSValue(); + } + arguments[i] = args.at(i).d->getValue(engine); + } + + Value result; + QV4::ExecutionContext *ctx = engine->current; + try { + result = f->construct(arguments.data(), arguments.size()); + } catch (Exception &e) { + e.accept(ctx); + result = e.value(); + } + + return new QJSValuePrivate(engine, result); } #ifdef QT_DEPRECATED @@ -553,12 +639,9 @@ QJSValue QJSValue::callAsConstructor(const QJSValueList &args) */ QJSEngine* QJSValue::engine() const { - Q_D(const QJSValue); - QScriptIsolate api(d->engine()); - QV8Engine* engine = d->engine(); + QV4::ExecutionEngine *engine = d->engine; if (engine) - return QV8Engine::get(engine); - return 0; + return engine->v8Engine->publicEngine(); } #endif // QT_DEPRECATED @@ -572,14 +655,18 @@ QJSEngine* QJSValue::engine() const */ QJSValue QJSValue::prototype() const { - Q_D(const QJSValue); - QScriptIsolate api(d->engine()); - return QJSValuePrivate::get(d->prototype()); + Object *o = d->value.asObject(); + if (!o) + return QJSValue(); + if (!o->prototype) + return QJSValue(NullValue); + return new QJSValuePrivate(o->internalClass->engine, Value::fromObject(o->prototype)); } /*! If this QJSValue is an object, sets the internal prototype (\c{__proto__} property) of this object to be \a prototype; + if the QJSValue is null, it sets the prototype to null; otherwise does nothing. The internal prototype should not be confused with the public @@ -590,9 +677,30 @@ QJSValue QJSValue::prototype() const */ void QJSValue::setPrototype(const QJSValue& prototype) { - Q_D(QJSValue); - QScriptIsolate api(d->engine()); - d->setPrototype(QJSValuePrivate::get(prototype)); + Object *o = d->value.asObject(); + if (!o) + return; + if (prototype.d->value.isNull()) { + o->prototype = 0; + return; + } + + Object *p = prototype.d->value.asObject(); + if (!p) + return; + if (o->engine() != p->engine()) { + qWarning("QJSValue::setPrototype() failed: cannot set a prototype created in a different engine"); + return; + } + Object *pp = p; + while (pp) { + if (pp == o) { + qWarning("QJSValue::setPrototype() failed: cyclic prototype value"); + return; + } + pp = pp->prototype; + } + o->prototype = p; } /*! @@ -604,8 +712,11 @@ void QJSValue::setPrototype(const QJSValue& prototype) */ QJSValue& QJSValue::operator=(const QJSValue& other) { - d_ptr = other.d_ptr; - return *this; + if (d == other.d) + return *this; + d->deref(); + d = other.d; + d->ref(); } /*! @@ -634,10 +745,7 @@ QJSValue& QJSValue::operator=(const QJSValue& other) */ bool QJSValue::equals(const QJSValue& other) const { - Q_D(const QJSValue); - QJSValuePrivate* otherValue = QJSValuePrivate::get(other); - QScriptIsolate api(d->engine() ? d->engine() : otherValue->engine()); - return d_ptr->equals(otherValue); + return __qmljs_equal(d->value, other.d->value); } /*! @@ -664,10 +772,7 @@ bool QJSValue::equals(const QJSValue& other) const */ bool QJSValue::strictlyEquals(const QJSValue& other) const { - Q_D(const QJSValue); - QJSValuePrivate* o = QJSValuePrivate::get(other); - QScriptIsolate api(d->engine() ? d->engine() : o->engine()); - return d_ptr->strictlyEquals(o); + return __qmljs_strict_equal(d->value, other.d->value); } /*! @@ -685,9 +790,25 @@ bool QJSValue::strictlyEquals(const QJSValue& other) const */ QJSValue QJSValue::property(const QString& name) const { - Q_D(const QJSValue); - QScriptIsolate api(d->engine()); - return QJSValuePrivate::get(d->property(name)); + Object *o = d->value.asObject(); + if (!o) + return QJSValue(); + + ExecutionEngine *engine = d->engine; + String *s = engine->newString(name); + uint idx = s->asArrayIndex(); + if (idx < UINT_MAX) + return property(idx); + + s->makeIdentifier(); + QV4::ExecutionContext *ctx = engine->current; + try { + QV4::Value v = o->get(s); + return new QJSValuePrivate(engine, v); + } catch (QV4::Exception &e) { + e.accept(ctx); + return new QJSValuePrivate(engine, e.value()); + } } /*! @@ -704,9 +825,19 @@ QJSValue QJSValue::property(const QString& name) const */ QJSValue QJSValue::property(quint32 arrayIndex) const { - Q_D(const QJSValue); - QScriptIsolate api(d->engine()); - return QJSValuePrivate::get(d->property(arrayIndex)); + Object *o = d->value.asObject(); + if (!o) + return QJSValue(); + + ExecutionEngine *engine = d->engine; + QV4::ExecutionContext *ctx = engine->current; + try { + QV4::Value v = arrayIndex == UINT_MAX ? o->get(engine->id_uintMax) : o->getIndexed(arrayIndex); + return new QJSValuePrivate(engine, v); + } catch (QV4::Exception &e) { + e.accept(ctx); + return new QJSValuePrivate(engine, e.value()); + } } /*! @@ -722,9 +853,30 @@ QJSValue QJSValue::property(quint32 arrayIndex) const */ void QJSValue::setProperty(const QString& name, const QJSValue& value) { - Q_D(QJSValue); - QScriptIsolate api(d->engine()); - d->setProperty(name, QJSValuePrivate::get(value)); + Object *o = d->value.asObject(); + if (!o) + return; + + if (!value.d->checkEngine(o->engine())) { + qWarning("QJSValue::setProperty(%s) failed: cannot set value created in a different engine", name.toUtf8().constData()); + return; + } + + ExecutionEngine *engine = d->engine; + String *s = engine->newString(name); + uint idx = s->asArrayIndex(); + if (idx < UINT_MAX) { + setProperty(idx, value); + return; + } + + QV4::ExecutionContext *ctx = engine->current; + s->makeIdentifier(); + try { + o->put(s, value.d->getValue(engine)); + } catch (QV4::Exception &e) { + e.accept(ctx); + } } /*! @@ -741,9 +893,20 @@ void QJSValue::setProperty(const QString& name, const QJSValue& value) */ void QJSValue::setProperty(quint32 arrayIndex, const QJSValue& value) { - Q_D(QJSValue); - QScriptIsolate api(d->engine()); - d->setProperty(arrayIndex, QJSValuePrivate::get(value)); + Object *o = d->value.asObject(); + if (!o) + return; + + ExecutionEngine *engine = d->engine; + QV4::ExecutionContext *ctx = engine->current; + try { + if (arrayIndex != UINT_MAX) + o->putIndexed(arrayIndex, value.d->getValue(engine)); + else + o->put(engine->id_uintMax, value.d->getValue(engine)); + } catch (QV4::Exception &e) { + e.accept(ctx); + } } /*! @@ -768,9 +931,13 @@ void QJSValue::setProperty(quint32 arrayIndex, const QJSValue& value) */ bool QJSValue::deleteProperty(const QString &name) { - Q_D(QJSValue); - QScriptIsolate api(d->engine()); - return d->deleteProperty(name); + Object *o = d->value.asObject(); + if (!o) + return false; + + ExecutionEngine *engine = d->engine; + String *s = engine->newString(name); + return o->deleteProperty(s); } /*! @@ -781,9 +948,13 @@ bool QJSValue::deleteProperty(const QString &name) */ bool QJSValue::hasProperty(const QString &name) const { - Q_D(const QJSValue); - QScriptIsolate api(d->engine()); - return d->hasProperty(name); + Object *o = d->value.asObject(); + if (!o) + return false; + + ExecutionEngine *engine = d->engine; + String *s = engine->newIdentifier(name); + return o->__hasProperty__(s); } /*! @@ -794,9 +965,13 @@ bool QJSValue::hasProperty(const QString &name) const */ bool QJSValue::hasOwnProperty(const QString &name) const { - Q_D(const QJSValue); - QScriptIsolate api(d->engine()); - return d->hasOwnProperty(name); + Object *o = d->value.asObject(); + if (!o) + return false; + + ExecutionEngine *engine = d->engine; + String *s = engine->newIdentifier(name); + return o->__getOwnProperty__(s); } /*! @@ -811,9 +986,11 @@ bool QJSValue::hasOwnProperty(const QString &name) const */ QObject *QJSValue::toQObject() const { - Q_D(const QJSValue); - QScriptIsolate api(d->engine()); - return d->toQObject(); + QV4::QObjectWrapper *o = d->value.as<QV4::QObjectWrapper>(); + if (!o) + return 0; + + return o->object(); } /*! @@ -825,9 +1002,10 @@ QObject *QJSValue::toQObject() const */ QDateTime QJSValue::toDateTime() const { - Q_D(const QJSValue); - QScriptIsolate api(d->engine()); - return d->toDataTime(); + QV4::DateObject *date = d->value.asDateObject(); + if (!date) + return QDateTime(); + return date->toQDateTime(); } /*! @@ -838,9 +1016,7 @@ QDateTime QJSValue::toDateTime() const */ bool QJSValue::isDate() const { - Q_D(const QJSValue); - QScriptIsolate api(d->engine()); - return d->isDate(); + return d->value.asDateObject(); } /*! @@ -849,9 +1025,7 @@ bool QJSValue::isDate() const */ bool QJSValue::isRegExp() const { - Q_D(const QJSValue); - QScriptIsolate api(d->engine()); - return d->isRegExp(); + return d->value.as<RegExpObject>(); } /*! @@ -865,35 +1039,7 @@ bool QJSValue::isRegExp() const */ bool QJSValue::isQObject() const { - Q_D(const QJSValue); - QScriptIsolate api(d->engine()); - return d->isQObject(); -} - -/*! - \internal - - Returns this value's internal V8 value, or an empty handle if - the QJSValue isn't bound to a QJSEngine. - - The V8 value enables direct use of the V8 API. - The caller is responsible for ensuring that a handle scope is in place. - Example: - - \code - QJSValue value = ...; - v8::HandleScope handleScope; - v8::Local<v8::Value> v8value = qt_QJSValueV8Value(value); - - // Do something with the V8 value (e.g., call v8::Value::IsInt32()) ... - \endcode - - \sa qt_QJSEngineV8Context() -*/ -Q_QML_EXPORT v8::Local<v8::Value> qt_QJSValueV8Value(const QJSValue &value) -{ - QJSValuePrivate *d = QJSValuePrivate::get(value); - return v8::Local<v8::Value>::New(d->handle()); + return d->value.as<QV4::QObjectWrapper>() != 0; } QT_END_NAMESPACE diff --git a/src/qml/qml/v8/qjsvalue.h b/src/qml/qml/v8/qjsvalue.h index efd52ce880..cf02ad819e 100644 --- a/src/qml/qml/v8/qjsvalue.h +++ b/src/qml/qml/v8/qjsvalue.h @@ -45,8 +45,7 @@ #include <QtQml/qtqmlglobal.h> #include <QtCore/qstring.h> #include <QtCore/qlist.h> -#include <QtCore/qsharedpointer.h> -#include <QtCore/qshareddata.h> +#include <QtCore/qmetatype.h> QT_BEGIN_NAMESPACE @@ -59,10 +58,7 @@ struct QMetaObject; class QDateTime; typedef QList<QJSValue> QJSValueList; - class QJSValuePrivate; -struct QScriptValuePrivatePointerDeleter; -template <class T> class QScriptPassPointer; class Q_QML_EXPORT QJSValue { @@ -137,18 +133,13 @@ public: QT_DEPRECATED QJSEngine *engine() const; #endif + QJSValue(QJSValuePrivate *dd); private: + friend class QJSValuePrivate; // force compile error, prevent QJSValue(bool) to be called - QJSValue(void *) Q_DECL_EQ_DELETE; - QJSValue(QJSValuePrivate*); - QJSValue(QScriptPassPointer<QJSValuePrivate>); - -private: - QExplicitlySharedDataPointer<QJSValuePrivate> d_ptr; - - Q_DECLARE_PRIVATE(QJSValue) + QJSValuePrivate *d; }; QT_END_NAMESPACE diff --git a/src/qml/qml/v8/qjsvalue_impl_p.h b/src/qml/qml/v8/qjsvalue_impl_p.h deleted file mode 100644 index 2e779c22e9..0000000000 --- a/src/qml/qml/v8/qjsvalue_impl_p.h +++ /dev/null @@ -1,950 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#ifndef QJSVALUE_IMPL_P_H -#define QJSVALUE_IMPL_P_H - -#include "qjsconverter_p.h" -#include "qjsvalue_p.h" -#include "qv8engine_p.h" -#include "qscriptisolate_p.h" - -QT_BEGIN_NAMESPACE - -QJSValuePrivate* QJSValuePrivate::get(const QJSValue& q) { Q_ASSERT(q.d_ptr.data()); return q.d_ptr.data(); } - -QJSValue QJSValuePrivate::get(const QJSValuePrivate* d) -{ - Q_ASSERT(d); - return QJSValue(const_cast<QJSValuePrivate*>(d)); -} - -QJSValue QJSValuePrivate::get(QScriptPassPointer<QJSValuePrivate> d) -{ - Q_ASSERT(d); - return QJSValue(d); -} - -QJSValue QJSValuePrivate::get(QJSValuePrivate* d) -{ - Q_ASSERT(d); - return QJSValue(d); -} - -QJSValuePrivate::QJSValuePrivate(bool value) - : m_engine(0), m_state(CBool), u(value) -{ -} - -QJSValuePrivate::QJSValuePrivate(int value) - : m_engine(0), m_state(CNumber), u(value) -{ -} - -QJSValuePrivate::QJSValuePrivate(uint value) - : m_engine(0), m_state(CNumber), u(value) -{ -} - -QJSValuePrivate::QJSValuePrivate(double value) - : m_engine(0), m_state(CNumber), u(value) -{ -} - -QJSValuePrivate::QJSValuePrivate(const QString& value) - : m_engine(0), m_state(CString), u(new QString(value)) -{ -} - -QJSValuePrivate::QJSValuePrivate(QJSValue::SpecialValue value) - : m_engine(0), m_state(value == QJSValue::NullValue ? CNull : CUndefined) -{ -} - -QJSValuePrivate::QJSValuePrivate(QV8Engine* engine, bool value) - : m_engine(engine), m_state(JSValue) -{ - Q_ASSERT(engine); - v8::HandleScope handleScope; - m_value = v8::Persistent<v8::Value>::New(m_engine->makeJSValue(value)); - m_engine->registerValue(this); -} - -QJSValuePrivate::QJSValuePrivate(QV8Engine* engine, int value) - : m_engine(engine), m_state(JSValue) -{ - Q_ASSERT(engine); - v8::HandleScope handleScope; - m_value = v8::Persistent<v8::Value>::New(m_engine->makeJSValue(value)); - m_engine->registerValue(this); -} - -QJSValuePrivate::QJSValuePrivate(QV8Engine* engine, uint value) - : m_engine(engine), m_state(JSValue) -{ - Q_ASSERT(engine); - v8::HandleScope handleScope; - m_value = v8::Persistent<v8::Value>::New(m_engine->makeJSValue(value)); - m_engine->registerValue(this); -} - -QJSValuePrivate::QJSValuePrivate(QV8Engine* engine, double value) - : m_engine(engine), m_state(JSValue) -{ - Q_ASSERT(engine); - v8::HandleScope handleScope; - m_value = v8::Persistent<v8::Value>::New(m_engine->makeJSValue(value)); - m_engine->registerValue(this); -} - -QJSValuePrivate::QJSValuePrivate(QV8Engine* engine, const QString& value) - : m_engine(engine), m_state(JSValue) -{ - Q_ASSERT(engine); - v8::HandleScope handleScope; - m_value = v8::Persistent<v8::Value>::New(m_engine->makeJSValue(value)); - m_engine->registerValue(this); -} - -QJSValuePrivate::QJSValuePrivate(QV8Engine* engine, QJSValue::SpecialValue value) - : m_engine(engine), m_state(JSValue) -{ - Q_ASSERT(engine); - v8::HandleScope handleScope; - m_value = v8::Persistent<v8::Value>::New(m_engine->makeJSValue(value)); - m_engine->registerValue(this); -} - -QJSValuePrivate::QJSValuePrivate(QV8Engine *engine, v8::Handle<v8::Value> value) - : m_engine(engine), m_state(JSValue), m_value(v8::Persistent<v8::Value>::New(value)) -{ - Q_ASSERT(engine); - // It shouldn't happen, v8 shows errors by returning an empty handler. This is important debug - // information and it can't be simply ignored. - Q_ASSERT(!value.IsEmpty()); - m_engine->registerValue(this); -} - -QJSValuePrivate::~QJSValuePrivate() -{ - if (isJSBased()) { - m_engine->unregisterValue(this); - QScriptIsolate api(m_engine); - m_value.Dispose(); - } else if (isStringBased()) { - delete u.m_string; - } -} - -bool QJSValuePrivate::toBool() const -{ - switch (m_state) { - case JSValue: - { - v8::HandleScope scope; - return m_value->ToBoolean()->Value(); - } - case CNumber: - return !(qIsNaN(u.m_number) || !u.m_number); - case CBool: - return u.m_bool; - case CNull: - case CUndefined: - return false; - case CString: - return u.m_string->length(); - } - - Q_ASSERT_X(false, "toBool()", "Not all states are included in the previous switch statement."); - return false; // Avoid compiler warning. -} - -double QJSValuePrivate::toNumber() const -{ - switch (m_state) { - case JSValue: - { - v8::HandleScope scope; - return m_value->ToNumber()->Value(); - } - case CNumber: - return u.m_number; - case CBool: - return u.m_bool ? 1 : 0; - case CNull: - case CUndefined: - return qQNaN(); - case CString: - bool ok; - double result = u.m_string->toDouble(&ok); - if (ok) - return result; - result = u.m_string->toInt(&ok, 0); // Try other bases. - if (ok) - return result; - if (*u.m_string == QLatin1String("Infinity")) - return qInf(); - if (*u.m_string == QLatin1String("-Infinity")) - return -qInf(); - return u.m_string->length() ? qQNaN() : 0; - } - - Q_ASSERT_X(false, "toNumber()", "Not all states are included in the previous switch statement."); - return 0; // Avoid compiler warning. -} - -QString QJSValuePrivate::toString() const -{ - switch (m_state) { - case CBool: - return u.m_bool ? QString::fromLatin1("true") : QString::fromLatin1("false"); - case CString: - return *u.m_string; - case CNumber: - return QJSConverter::toString(u.m_number); - case CNull: - return QString::fromLatin1("null"); - case CUndefined: - return QString::fromLatin1("undefined"); - case JSValue: - Q_ASSERT(!m_value.IsEmpty()); - v8::HandleScope handleScope; - v8::TryCatch tryCatch; - v8::Local<v8::String> result = m_value->ToString(); - if (result.IsEmpty()) - result = tryCatch.Exception()->ToString(); - return QJSConverter::toString(result); - } - - Q_ASSERT_X(false, "toString()", "Not all states are included in the previous switch statement."); - return QString(); // Avoid compiler warning. -} - -QVariant QJSValuePrivate::toVariant() const -{ - switch (m_state) { - case CBool: - return QVariant(u.m_bool); - case CString: - return QVariant(*u.m_string); - case CNumber: - return QVariant(u.m_number); - case CNull: - return QVariant(QMetaType::VoidStar, 0); - case CUndefined: - return QVariant(); - case JSValue: - break; - } - - Q_ASSERT(m_state == JSValue); - Q_ASSERT(!m_value.IsEmpty()); - Q_ASSERT(m_engine); - - v8::HandleScope handleScope; - return m_engine->variantFromJS(m_value); -} - -inline QDateTime QJSValuePrivate::toDataTime() const -{ - if (!isDate()) - return QDateTime(); - - v8::HandleScope handleScope; - return QJSConverter::toDateTime(v8::Handle<v8::Date>::Cast(m_value)); - -} - -QObject* QJSValuePrivate::toQObject() const -{ - if (!isJSBased()) - return 0; - - v8::HandleScope handleScope; - return engine()->qtObjectFromJS(m_value); -} - -double QJSValuePrivate::toInteger() const -{ - double result = toNumber(); - if (qIsNaN(result)) - return 0; - if (qIsInf(result)) - return result; - - // Must use floor explicitly rather than qFloor here. On some - // platforms qFloor will cast the value to a single precision float and use - // floorf() which results in test failures. - return (result > 0) ? floor(result) : -1 * floor(-result); -} - -qint32 QJSValuePrivate::toInt32() const -{ - double result = toInteger(); - // Orginaly it should look like that (result == 0 || qIsInf(result) || qIsNaN(result)), but - // some of these operation are invoked in toInteger subcall. - if (qIsInf(result)) - return 0; - return result; -} - -quint32 QJSValuePrivate::toUInt32() const -{ - double result = toInteger(); - // Orginaly it should look like that (result == 0 || qIsInf(result) || qIsNaN(result)), but - // some of these operation are invoked in toInteger subcall. - if (qIsInf(result)) - return 0; - - // The explicit casts are required to avoid undefined behaviour. For example, casting - // a negative double directly to an unsigned int on ARM NEON FPU results in the value - // being set to zero. Casting to a signed int first ensures well defined behaviour. - return (quint32) (qint32) result; -} - -quint16 QJSValuePrivate::toUInt16() const -{ - return toInt32(); -} - -inline bool QJSValuePrivate::isArray() const -{ - return isJSBased() && m_value->IsArray(); -} - -inline bool QJSValuePrivate::isBool() const -{ - return m_state == CBool || (isJSBased() && m_value->IsBoolean()); -} - -inline bool QJSValuePrivate::isCallable() const -{ - if (isFunction()) - return true; - if (isObject()) { - // Our C++ wrappers register function handlers but not always act as callables. - return v8::Object::Cast(*m_value)->IsCallable(); - } - return false; -} - -inline bool QJSValuePrivate::isError() const -{ - if (!isJSBased()) - return false; - v8::HandleScope handleScope; - return m_value->IsError(); -} - -inline bool QJSValuePrivate::isFunction() const -{ - return isJSBased() && m_value->IsFunction(); -} - -inline bool QJSValuePrivate::isNull() const -{ - return m_state == CNull || (isJSBased() && m_value->IsNull()); -} - -inline bool QJSValuePrivate::isNumber() const -{ - return m_state == CNumber || (isJSBased() && m_value->IsNumber()); -} - -inline bool QJSValuePrivate::isObject() const -{ - return isJSBased() && m_value->IsObject(); -} - -inline bool QJSValuePrivate::isString() const -{ - return m_state == CString || (isJSBased() && m_value->IsString()); -} - -inline bool QJSValuePrivate::isUndefined() const -{ - return m_state == CUndefined || (isJSBased() && m_value->IsUndefined()); -} - -inline bool QJSValuePrivate::isVariant() const -{ - return isJSBased() && m_engine->isVariant(m_value); -} - -bool QJSValuePrivate::isDate() const -{ - return (isJSBased() && m_value->IsDate()); -} - -bool QJSValuePrivate::isRegExp() const -{ - return (isJSBased() && m_value->IsRegExp()); -} - -bool QJSValuePrivate::isQObject() const -{ - return isJSBased() && engine()->isQObject(m_value); -} - -inline bool QJSValuePrivate::equals(QJSValuePrivate* other) -{ - if (!isJSBased() && !other->isJSBased()) { - switch (m_state) { - case CNull: - case CUndefined: - return other->isUndefined() || other->isNull(); - case CNumber: - switch (other->m_state) { - case CBool: - case CString: - return u.m_number == other->toNumber(); - case CNumber: - return u.m_number == other->u.m_number; - default: - return false; - } - case CBool: - switch (other->m_state) { - case CBool: - return u.m_bool == other->u.m_bool; - case CNumber: - return toNumber() == other->u.m_number; - case CString: - return toNumber() == other->toNumber(); - default: - return false; - } - case CString: - switch (other->m_state) { - case CBool: - return toNumber() == other->toNumber(); - case CNumber: - return toNumber() == other->u.m_number; - case CString: - return *u.m_string == *other->u.m_string; - default: - return false; - } - default: - Q_ASSERT_X(false, "QJSValue::equals", "Not all states are included in the previous switch statement."); - } - } - - v8::HandleScope handleScope; - if (isJSBased() && !other->isJSBased()) { - if (!other->assignEngine(engine())) { - qWarning("QJSValue::equals: cannot compare to a value created in a different engine"); - return false; - } - } else if (!isJSBased() && other->isJSBased()) { - if (!assignEngine(other->engine())) { - qWarning("QJSValue::equals: cannot compare to a value created in a different engine"); - return false; - } - } - - Q_ASSERT(this->engine() && other->engine()); - if (this->engine() != other->engine()) { - qWarning("QJSValue::equals: cannot compare to a value created in a different engine"); - return false; - } - return m_value->Equals(other->m_value); -} - -inline bool QJSValuePrivate::strictlyEquals(QJSValuePrivate* other) -{ - if (isJSBased()) { - // We can't compare these two values without binding to the same engine. - if (!other->isJSBased()) { - if (other->assignEngine(engine())) - return m_value->StrictEquals(other->m_value); - return false; - } - if (other->engine() != engine()) { - qWarning("QJSValue::strictlyEquals: cannot compare to a value created in a different engine"); - return false; - } - return m_value->StrictEquals(other->m_value); - } - if (isStringBased()) { - if (other->isStringBased()) - return *u.m_string == *(other->u.m_string); - if (other->isJSBased()) { - assignEngine(other->engine()); - return m_value->StrictEquals(other->m_value); - } - } - if (isNumberBased()) { - if (other->isJSBased()) { - assignEngine(other->engine()); - return m_value->StrictEquals(other->m_value); - } - if (m_state != other->m_state) - return false; - if (m_state == CNumber) - return u.m_number == other->u.m_number; - Q_ASSERT(m_state == CBool); - return u.m_bool == other->u.m_bool; - } - - return (isUndefined() && other->isUndefined()) - || (isNull() && other->isNull()); -} - -inline QScriptPassPointer<QJSValuePrivate> QJSValuePrivate::prototype() const -{ - if (isObject()) { - v8::HandleScope handleScope; - return new QJSValuePrivate(engine(), v8::Handle<v8::Object>::Cast(m_value)->GetPrototype()); - } - return new QJSValuePrivate(); -} - -inline void QJSValuePrivate::setPrototype(QJSValuePrivate* prototype) -{ - if (isObject() && (prototype->isObject() || prototype->isNull())) { - if (engine() != prototype->engine()) { - if (prototype->engine()) { - qWarning("QJSValue::setPrototype() failed: cannot set a prototype created in a different engine"); - return; - } - prototype->assignEngine(engine()); - } - v8::HandleScope handleScope; - if (!v8::Handle<v8::Object>::Cast(m_value)->SetPrototype(*prototype)) - qWarning("QJSValue::setPrototype() failed: cyclic prototype value"); - } -} - -inline void QJSValuePrivate::setProperty(const QString& name, QJSValuePrivate* value, uint attribs) -{ - if (!isObject()) - return; - v8::HandleScope handleScope; - setProperty(QJSConverter::toString(name), value, attribs); -} - -inline void QJSValuePrivate::setProperty(v8::Handle<v8::String> name, QJSValuePrivate* value, uint attribs) -{ - if (!isObject()) - return; - - if (!value->isJSBased()) - value->assignEngine(engine()); - - if (engine() != value->engine()) { - qWarning("QJSValue::setProperty(%s) failed: " - "cannot set value created in a different engine", - qPrintable(QJSConverter::toString(name))); - return; - } - - v8::TryCatch tryCatch; -// if (attribs & (QJSValue::PropertyGetter | QJSValue::PropertySetter)) { -// engine()->originalGlobalObject()->defineGetterOrSetter(*this, name, value->m_value, attribs); -// } else { - v8::Object::Cast(*m_value)->Set(name, value->m_value, v8::PropertyAttribute(attribs & QJSConverter::PropertyAttributeMask)); -// } -} - -inline void QJSValuePrivate::setProperty(quint32 index, QJSValuePrivate* value, uint attribs) -{ - // FIXME this method should by integrated with other overloads to use the same code patch. - // for now it is not possible as v8 doesn't allow to set property attributes using index based api. - - if (!isObject()) - return; - - if (attribs) { - // FIXME we don't need to convert index to a string. - //Object::Set(int,value) do not take attributes. - setProperty(QString::number(index), value, attribs); - return; - } - - if (!value->isJSBased()) - value->assignEngine(engine()); - - if (engine() != value->engine()) { - qWarning("QJSValue::setProperty() failed: cannot set value created in a different engine"); - return; - } - - v8::HandleScope handleScope; - v8::Object::Cast(*m_value)->Set(index, value->m_value); -} - -inline QScriptPassPointer<QJSValuePrivate> QJSValuePrivate::property(const QString& name) const -{ - if (!isObject()) - return new QJSValuePrivate(); - if (!name.length()) - return new QJSValuePrivate(engine()); - - v8::HandleScope handleScope; - return property(QJSConverter::toString(name)); -} - -inline QScriptPassPointer<QJSValuePrivate> QJSValuePrivate::property(v8::Handle<v8::String> name) const -{ - Q_ASSERT(!name.IsEmpty()); - if (!isObject()) - return new QJSValuePrivate(); - return property<>(name); -} - -inline QScriptPassPointer<QJSValuePrivate> QJSValuePrivate::property(quint32 index) const -{ - if (!isObject()) - return new QJSValuePrivate(); - return property<>(index); -} - -template<typename T> -inline QScriptPassPointer<QJSValuePrivate> QJSValuePrivate::property(T name) const -{ - Q_ASSERT(isObject()); - v8::HandleScope handleScope; - v8::Handle<v8::Object> self(v8::Object::Cast(*m_value)); - - v8::TryCatch tryCatch; - v8::Handle<v8::Value> result = self->Get(name); - if (tryCatch.HasCaught()) - result = tryCatch.Exception(); - if (result.IsEmpty()) - return new QJSValuePrivate(engine()); - return new QJSValuePrivate(engine(), result); -} - -inline bool QJSValuePrivate::deleteProperty(const QString& name) -{ - if (!isObject()) - return false; - - v8::HandleScope handleScope; - v8::Handle<v8::Object> self(v8::Handle<v8::Object>::Cast(m_value)); - return self->Delete(QJSConverter::toString(name)); -} - -inline bool QJSValuePrivate::hasProperty(const QString &name) const -{ - if (!isObject()) - return false; - - v8::HandleScope handleScope; - v8::Handle<v8::Object> self(v8::Handle<v8::Object>::Cast(m_value)); - return self->Has(QJSConverter::toString(name)); -} - -inline bool QJSValuePrivate::hasOwnProperty(const QString &name) const -{ - if (!isObject()) - return false; - - v8::HandleScope handleScope; - v8::Handle<v8::Object> self(v8::Handle<v8::Object>::Cast(m_value)); - return self->HasOwnProperty(QJSConverter::toString(name)); -} - -inline QJSValuePrivate::PropertyFlags QJSValuePrivate::propertyFlags(const QString& name) const -{ - if (!isObject()) - return QJSValuePrivate::PropertyFlags(0); - - v8::HandleScope handleScope; - return engine()->getPropertyFlags(v8::Handle<v8::Object>::Cast(m_value), QJSConverter::toString(name)); -} - -inline QJSValuePrivate::PropertyFlags QJSValuePrivate::propertyFlags(v8::Handle<v8::String> name) const -{ - if (!isObject()) - return QJSValuePrivate::PropertyFlags(0); - - v8::HandleScope handleScope; - return engine()->getPropertyFlags(v8::Handle<v8::Object>::Cast(m_value), name); -} - -inline QScriptPassPointer<QJSValuePrivate> QJSValuePrivate::call(QJSValuePrivate* thisObject, const QJSValueList& args) -{ - if (!isCallable()) - return new QJSValuePrivate(); - - v8::HandleScope handleScope; - - // Convert all arguments and bind to the engine. - int argc = args.size(); - QVarLengthArray<v8::Handle<v8::Value>, 8> argv(argc); - if (!prepareArgumentsForCall(argv.data(), args)) { - qWarning("QJSValue::call() failed: cannot call function with argument created in a different engine"); - return new QJSValuePrivate(engine()); - } - - return call(thisObject, argc, argv.data()); -} - -QScriptPassPointer<QJSValuePrivate> QJSValuePrivate::call(QJSValuePrivate* thisObject, int argc, v8::Handle<v8::Value> *argv) -{ - QV8Engine *e = engine(); - - v8::Handle<v8::Object> recv; - - if (!thisObject || !thisObject->isObject()) { - recv = v8::Handle<v8::Object>(v8::Object::Cast(*e->global())); - } else { - if (!thisObject->assignEngine(e)) { - qWarning("QJSValue::call() failed: cannot call function with thisObject created in a different engine"); - return new QJSValuePrivate(engine()); - } - - recv = v8::Handle<v8::Object>(v8::Object::Cast(*thisObject->m_value)); - } - - if (argc < 0) { - v8::Local<v8::Value> exeption = v8::Exception::TypeError(v8::String::New("Arguments must be an array")); - return new QJSValuePrivate(e, exeption); - } - - v8::TryCatch tryCatch; - v8::Handle<v8::Value> result = v8::Object::Cast(*m_value)->CallAsFunction(recv, argc, argv); - - if (result.IsEmpty()) { - result = tryCatch.Exception(); - // TODO: figure out why v8 doesn't always produce an exception value. - //Q_ASSERT(!result.IsEmpty()); - if (result.IsEmpty()) - result = v8::Exception::Error(v8::String::New("missing exception value")); - } - - return new QJSValuePrivate(e, result); -} - -inline QScriptPassPointer<QJSValuePrivate> QJSValuePrivate::callAsConstructor(int argc, v8::Handle<v8::Value> *argv) -{ - QV8Engine *e = engine(); - - if (argc < 0) { - v8::Local<v8::Value> exeption = v8::Exception::TypeError(v8::String::New("Arguments must be an array")); - return new QJSValuePrivate(e, exeption); - } - - v8::TryCatch tryCatch; - v8::Handle<v8::Value> result = v8::Object::Cast(*m_value)->CallAsConstructor(argc, argv); - - if (result.IsEmpty()) - result = tryCatch.Exception(); - - return new QJSValuePrivate(e, result); -} - -inline QScriptPassPointer<QJSValuePrivate> QJSValuePrivate::callAsConstructor(const QJSValueList& args) -{ - if (!isCallable()) - return new QJSValuePrivate(); - - v8::HandleScope handleScope; - - // Convert all arguments and bind to the engine. - int argc = args.size(); - QVarLengthArray<v8::Handle<v8::Value>, 8> argv(argc); - if (!prepareArgumentsForCall(argv.data(), args)) { - qWarning("QJSValue::callAsConstructor() failed: cannot construct function with argument created in a different engine"); - return new QJSValuePrivate(engine()); - } - - return callAsConstructor(argc, argv.data()); -} - -/*! \internal - * Make sure this value is associated with a v8 value belonging to this engine. - * If the value belongs to another engine, returns false. - */ -bool QJSValuePrivate::assignEngine(QV8Engine* engine) -{ - Q_ASSERT(engine); - v8::HandleScope handleScope; - switch (m_state) { - case CBool: - m_value = v8::Persistent<v8::Value>::New(engine->makeJSValue(u.m_bool)); - break; - case CString: - m_value = v8::Persistent<v8::Value>::New(engine->makeJSValue(*u.m_string)); - delete u.m_string; - break; - case CNumber: - m_value = v8::Persistent<v8::Value>::New(engine->makeJSValue(u.m_number)); - break; - case CNull: - m_value = v8::Persistent<v8::Value>::New(engine->makeJSValue(QJSValue::NullValue)); - break; - case CUndefined: - m_value = v8::Persistent<v8::Value>::New(engine->makeJSValue(QJSValue::UndefinedValue)); - break; - default: - if (this->engine() == engine) - return true; - else if (!isJSBased()) - Q_ASSERT_X(!isJSBased(), "assignEngine()", "Not all states are included in the previous switch statement."); - else - qWarning("JSValue can't be rassigned to an another engine."); - return false; - } - m_engine = engine; - m_state = JSValue; - - m_engine->registerValue(this); - return true; -} - -/*! - \internal - Invalidates this value (makes it undefined). - - Does not remove the value from the engine's list of - registered values; that's the responsibility of the caller. -*/ -void QJSValuePrivate::invalidate() -{ - if (isJSBased()) { - m_value.Dispose(); - m_value.Clear(); - } else if (isStringBased()) { - delete u.m_string; - } - m_engine = 0; - m_state = CUndefined; -} - -QV8Engine* QJSValuePrivate::engine() const -{ - return m_engine; -} - -inline QJSValuePrivate::operator v8::Handle<v8::Value>() const -{ - Q_ASSERT(isJSBased()); - return m_value; -} - -inline QJSValuePrivate::operator v8::Handle<v8::Object>() const -{ - Q_ASSERT(isObject()); - return v8::Handle<v8::Object>::Cast(m_value); -} - -inline v8::Handle<v8::Value> QJSValuePrivate::handle() const -{ - return m_value; -} - -/*! - * Return a v8::Handle, assign to the engine if needed. - */ -v8::Handle<v8::Value> QJSValuePrivate::asV8Value(QV8Engine* engine) -{ - if (!m_engine) { - if (!assignEngine(engine)) - return v8::Handle<v8::Value>(); - } - Q_ASSERT(isJSBased()); - return m_value; -} - -/*! - \internal - Returns true if QSV have an engine associated. -*/ -bool QJSValuePrivate::isJSBased() const -{ -#ifndef QT_NO_DEBUG - // internals check. - if (m_state >= JSValue) - Q_ASSERT(!m_value.IsEmpty()); - else - Q_ASSERT(m_value.IsEmpty()); -#endif - return m_state >= JSValue; -} - -/*! - \internal - Returns true if current value of QSV is placed in m_number. -*/ -bool QJSValuePrivate::isNumberBased() const { return m_state == CNumber || m_state == CBool; } - -/*! - \internal - Returns true if current value of QSV is placed in m_string. -*/ -bool QJSValuePrivate::isStringBased() const { return m_state == CString; } - -/*! - \internal - Converts arguments and bind them to the engine. - \attention argv should be big enough -*/ -inline bool QJSValuePrivate::prepareArgumentsForCall(v8::Handle<v8::Value> argv[], const QJSValueList& args) const -{ - QJSValueList::const_iterator i = args.constBegin(); - for (int j = 0; i != args.constEnd(); j++, i++) { - QJSValuePrivate* value = QJSValuePrivate::get(*i); - if ((value->isJSBased() && engine() != value->engine()) - || (!value->isJSBased() && !value->assignEngine(engine()))) - // Different engines are not allowed! - return false; - argv[j] = *value; - } - return true; -} - -QT_END_NAMESPACE - -#endif diff --git a/src/qml/qml/v8/qjsvalue_p.h b/src/qml/qml/v8/qjsvalue_p.h index c4c8d415d4..ef94dea555 100644 --- a/src/qml/qml/v8/qjsvalue_p.h +++ b/src/qml/qml/v8/qjsvalue_p.h @@ -53,161 +53,47 @@ #ifndef QJSVALUE_P_H #define QJSVALUE_P_H -#include <private/qv8_p.h> - -#include <QtCore/qbytearray.h> -#include <QtCore/qdatetime.h> -#include <QtCore/qmath.h> -#include <QtCore/qvarlengtharray.h> -#include <qdebug.h> - -#include <private/qintrusivelist_p.h> -#include "qscriptshareddata_p.h" -#include "qjsvalue.h" +#include <qjsvalue.h> +#include <private/qv4value_p.h> +#include <private/qv4string_p.h> +#include <private/qv4engine_p.h> +#include <private/qv4object_p.h> QT_BEGIN_NAMESPACE -class QV8Engine; - /*! \internal \class QJSValuePrivate */ -class QJSValuePrivate - : public QSharedData +class QJSValuePrivate : public QV4::PersistentValuePrivate { public: - enum PropertyFlag { - ReadOnly = 0x00000001, - Undeletable = 0x00000002, - SkipInEnumeration = 0x00000004 - }; - Q_DECLARE_FLAGS(PropertyFlags, PropertyFlag) - - inline static QJSValuePrivate* get(const QJSValue& q); - inline static QJSValue get(const QJSValuePrivate* d); - inline static QJSValue get(QJSValuePrivate* d); - inline static QJSValue get(QScriptPassPointer<QJSValuePrivate> d); - inline ~QJSValuePrivate(); - - inline QJSValuePrivate(bool value); - inline QJSValuePrivate(int value); - inline QJSValuePrivate(uint value); - inline QJSValuePrivate(double value); - inline QJSValuePrivate(const QString& value); - inline QJSValuePrivate(QJSValue::SpecialValue value = QJSValue::UndefinedValue); - - inline QJSValuePrivate(QV8Engine *engine, bool value); - inline QJSValuePrivate(QV8Engine *engine, int value); - inline QJSValuePrivate(QV8Engine *engine, uint value); - inline QJSValuePrivate(QV8Engine *engine, double value); - inline QJSValuePrivate(QV8Engine *engine, const QString& value); - inline QJSValuePrivate(QV8Engine *engine, QJSValue::SpecialValue value = QJSValue::UndefinedValue); - inline QJSValuePrivate(QV8Engine *engine, v8::Handle<v8::Value>); - inline void invalidate(); - - inline bool toBool() const; - inline double toNumber() const; - inline QString toString() const; - inline double toInteger() const; - inline qint32 toInt32() const; - inline quint32 toUInt32() const; - inline quint16 toUInt16() const; - inline QDateTime toDataTime() const; - inline QObject *toQObject() const; - inline QVariant toVariant() const; - - inline bool isArray() const; - inline bool isBool() const; - inline bool isCallable() const; - inline bool isError() const; - inline bool isFunction() const; - inline bool isNull() const; - inline bool isNumber() const; - inline bool isObject() const; - inline bool isString() const; - inline bool isUndefined() const; - inline bool isVariant() const; - inline bool isDate() const; - inline bool isRegExp() const; - inline bool isQObject() const; - - inline bool equals(QJSValuePrivate* other); - inline bool strictlyEquals(QJSValuePrivate* other); - - inline QScriptPassPointer<QJSValuePrivate> prototype() const; - inline void setPrototype(QJSValuePrivate* prototype); - - inline void setProperty(const QString &name, QJSValuePrivate *value, uint attribs = 0); - inline void setProperty(v8::Handle<v8::String> name, QJSValuePrivate *value, uint attribs = 0); - inline void setProperty(quint32 index, QJSValuePrivate* value, uint attribs = 0); - inline QScriptPassPointer<QJSValuePrivate> property(const QString& name) const; - inline QScriptPassPointer<QJSValuePrivate> property(v8::Handle<v8::String> name) const; - inline QScriptPassPointer<QJSValuePrivate> property(quint32 index) const; - template<typename T> - inline QScriptPassPointer<QJSValuePrivate> property(T name) const; - inline bool deleteProperty(const QString& name); - inline bool hasProperty(const QString &name) const; - inline bool hasOwnProperty(const QString &name) const; - inline PropertyFlags propertyFlags(const QString& name) const; - inline PropertyFlags propertyFlags(v8::Handle<v8::String> name) const; - - inline QScriptPassPointer<QJSValuePrivate> call(QJSValuePrivate* thisObject, const QJSValueList& args); - inline QScriptPassPointer<QJSValuePrivate> call(QJSValuePrivate* thisObject, const QJSValue& arguments); - inline QScriptPassPointer<QJSValuePrivate> call(QJSValuePrivate* thisObject, int argc, v8::Handle< v8::Value >* argv); - inline QScriptPassPointer<QJSValuePrivate> callAsConstructor(int argc, v8::Handle<v8::Value> *argv); - inline QScriptPassPointer<QJSValuePrivate> callAsConstructor(const QJSValueList& args); - inline QScriptPassPointer<QJSValuePrivate> callAsConstructor(const QJSValue& arguments); - - inline bool assignEngine(QV8Engine *engine); - inline QV8Engine *engine() const; - - inline operator v8::Handle<v8::Value>() const; - inline operator v8::Handle<v8::Object>() const; - inline v8::Handle<v8::Value> handle() const; - inline v8::Handle<v8::Value> asV8Value(QV8Engine *engine); -private: - QIntrusiveListNode m_node; - QV8Engine *m_engine; - - // Please, update class documentation when you change the enum. - enum State { - CString = 0x1000, - CNumber, - CBool, - CNull, - CUndefined, - JSValue = 0x2000 // V8 values are equal or higher then this value. - // JSPrimitive, - // JSObject - } m_state; - - union CValue { - bool m_bool; - double m_number; - QString* m_string; - - CValue() : m_number(0) {} - CValue(bool value) : m_bool(value) {} - CValue(int number) : m_number(number) {} - CValue(uint number) : m_number(number) {} - CValue(double number) : m_number(number) {} - CValue(QString* string) : m_string(string) {} - } u; - // v8::Persistent is not a POD, so can't be part of the union. - v8::Persistent<v8::Value> m_value; - - Q_DISABLE_COPY(QJSValuePrivate) - inline bool isJSBased() const; - inline bool isNumberBased() const; - inline bool isStringBased() const; - inline bool prepareArgumentsForCall(v8::Handle<v8::Value> argv[], const QJSValueList& arguments) const; - - friend class QV8Engine; + QJSValuePrivate(QV4::ExecutionEngine *engine, const QV4::Value &v) + : PersistentValuePrivate(v, engine) + { + if (value.isEmpty()) + value = QV4::Value::undefinedValue(); + } + QJSValuePrivate(QV4::Object *o) + : PersistentValuePrivate(QV4::Value::fromObject(o)) + { } + QJSValuePrivate(QV4::String *s) + : PersistentValuePrivate(QV4::Value::fromString(s)) + { } + QJSValuePrivate(const QString &s) + : PersistentValuePrivate(QV4::Value::undefinedValue()) + , string(0, s) + { + value = QV4::Value::fromString(&string); + } + + QV4::Value getValue(QV4::ExecutionEngine *e); + + static QJSValuePrivate *get(const QJSValue &v) { return v.d; } + + QV4::String string; }; -Q_DECLARE_OPERATORS_FOR_FLAGS(QJSValuePrivate::PropertyFlags) - QT_END_NAMESPACE #endif diff --git a/src/qml/qml/v8/qjsvalueiterator.cpp b/src/qml/qml/v8/qjsvalueiterator.cpp index 67646c9eb4..a6fba112c9 100644 --- a/src/qml/qml/v8/qjsvalueiterator.cpp +++ b/src/qml/qml/v8/qjsvalueiterator.cpp @@ -41,14 +41,25 @@ #include "qjsvalueiterator.h" #include "qjsvalueiterator_p.h" - -#include "qscriptisolate_p.h" #include "qjsvalue_p.h" -#include "qv8engine_p.h" -#include "qscript_impl_p.h" +#include "private/qv4string_p.h" +#include "private/qv4object_p.h" QT_BEGIN_NAMESPACE +QJSValueIteratorPrivate::QJSValueIteratorPrivate(const QJSValue &v) + : value(v) + , iterator(QJSValuePrivate::get(v)->value.asObject(), QV4::ObjectIterator::NoFlags) + , currentValue(0) + , currentName(0) + , currentIndex(UINT_MAX) + , nextValue(0) + , nextName(0) + , nextIndex(UINT_MAX) +{ +} + + /*! \class QJSValueIterator @@ -84,14 +95,17 @@ QT_BEGIN_NAMESPACE first property). */ QJSValueIterator::QJSValueIterator(const QJSValue& object) - : d_ptr(new QJSValueIteratorPrivate(QJSValuePrivate::get(object))) -{} + : d_ptr(new QJSValueIteratorPrivate(object)) +{ + d_ptr->nextValue = d_ptr->iterator.next(&d_ptr->nextName, &d_ptr->nextIndex, &d_ptr->nextAttributes); +} /*! Destroys the iterator. */ QJSValueIterator::~QJSValueIterator() -{} +{ +} /*! Returns true if there is at least one item ahead of the iterator @@ -102,9 +116,9 @@ QJSValueIterator::~QJSValueIterator() */ bool QJSValueIterator::hasNext() const { - Q_D(const QJSValueIterator); - QScriptIsolate api(d->engine()); - return d->hasNext(); + if (!QJSValuePrivate::get(d_ptr->value)->value.isObject()) + return false; + return d_ptr->nextValue != 0; } /*! @@ -120,9 +134,15 @@ bool QJSValueIterator::hasNext() const */ bool QJSValueIterator::next() { - Q_D(QJSValueIterator); - QScriptIsolate api(d->engine()); - return d->next(); + if (!QJSValuePrivate::get(d_ptr->value)->value.isObject()) + return false; + d_ptr->currentValue = d_ptr->nextValue; + d_ptr->currentName = d_ptr->nextName; + d_ptr->currentIndex = d_ptr->nextIndex; + d_ptr->currentAttributes = d_ptr->nextAttributes; + + d_ptr->nextValue = d_ptr->iterator.next(&d_ptr->nextName, &d_ptr->nextIndex, &d_ptr->nextAttributes); + return d_ptr->nextValue != 0; } /*! @@ -133,9 +153,13 @@ bool QJSValueIterator::next() */ QString QJSValueIterator::name() const { - Q_D(const QJSValueIterator); - QScriptIsolate api(d->engine()); - return d_ptr->name(); + if (!QJSValuePrivate::get(d_ptr->value)->value.isObject()) + return false; + if (d_ptr->currentName) + return d_ptr->currentName->toQString(); + if (d_ptr->currentIndex < UINT_MAX) + return QString::number(d_ptr->currentIndex); + return QString(); } @@ -147,9 +171,21 @@ QString QJSValueIterator::name() const */ QJSValue QJSValueIterator::value() const { - Q_D(const QJSValueIterator); - QScriptIsolate api(d->engine()); - return QJSValuePrivate::get(d->value()); + if (!QJSValuePrivate::get(d_ptr->value)->value.isObject()) + return QJSValue(); + if (!d_ptr->currentValue) + return QJSValue(); + + QV4::Object *o = d_ptr->iterator.object; + QV4::ExecutionEngine *engine = o->internalClass->engine; + QV4::ExecutionContext *ctx = engine->current; + try { + QV4::Value v = o->getValue(d_ptr->currentValue, d_ptr->currentAttributes); + return new QJSValuePrivate(engine, v); + } catch (QV4::Exception &e) { + e.accept(ctx); + return QJSValue(); + } } @@ -160,9 +196,8 @@ QJSValue QJSValueIterator::value() const */ QJSValueIterator& QJSValueIterator::operator=(QJSValue& object) { - Q_D(QJSValueIterator); - QScriptIsolate api(d->engine()); - d_ptr.reset(new QJSValueIteratorPrivate(QJSValuePrivate::get(object))); + d_ptr->iterator = QV4::ObjectIterator(QJSValuePrivate::get(object)->value.asObject(), QV4::ObjectIterator::NoFlags); + d_ptr->nextValue = d_ptr->iterator.next(&d_ptr->nextName, &d_ptr->nextIndex, &d_ptr->nextAttributes); return *this; } diff --git a/src/qml/qml/v8/qjsvalueiterator.h b/src/qml/qml/v8/qjsvalueiterator.h index b4f90a44b7..e204558e90 100644 --- a/src/qml/qml/v8/qjsvalueiterator.h +++ b/src/qml/qml/v8/qjsvalueiterator.h @@ -42,8 +42,8 @@ #ifndef QSCRIPTVALUEITERATOR_H #define QSCRIPTVALUEITERATOR_H -#include <QtQml/qtqmlglobal.h> #include <QtQml/qjsvalue.h> +#include <QtQml/qtqmlglobal.h> #include <QtCore/qscopedpointer.h> QT_BEGIN_NAMESPACE diff --git a/src/qml/qml/v8/qjsvalueiterator_impl_p.h b/src/qml/qml/v8/qjsvalueiterator_impl_p.h deleted file mode 100644 index f7b6943f57..0000000000 --- a/src/qml/qml/v8/qjsvalueiterator_impl_p.h +++ /dev/null @@ -1,143 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QJSVALUEITERATOR_IMPL_P_H -#define QJSVALUEITERATOR_IMPL_P_H - -#include "qjsvalueiterator_p.h" -#include <private/qv8engine_p.h> -#include "qjsconverter_p.h" - -QT_BEGIN_NAMESPACE - -inline QJSValueIteratorPrivate::QJSValueIteratorPrivate(const QJSValuePrivate* value) - : m_object(const_cast<QJSValuePrivate*>(value)) - , m_index(0) - , m_count(0) -{ - Q_ASSERT(value); - QV8Engine *engine = m_object->engine(); - if (!m_object->isObject()) - m_object = 0; - else { - QScriptIsolate api(engine, QScriptIsolate::NotNullEngine); - v8::HandleScope scope; - - v8::Handle<v8::Value> tmp = *value; - v8::Handle<v8::Object> obj = v8::Handle<v8::Object>::Cast(tmp); - v8::Local<v8::Array> names; - - // FIXME we need newer V8! - //names = obj->GetOwnPropertyNames(); - names = engine->getOwnPropertyNames(obj); - m_names = v8::Persistent<v8::Array>::New(names); - m_count = names->Length(); - - engine->registerValueIterator(this); - } -} - -inline QJSValueIteratorPrivate::~QJSValueIteratorPrivate() -{ - if (isValid()) { - engine()->unregisterValueIterator(this); - m_names.Dispose(); - } -} - -inline void QJSValueIteratorPrivate::invalidate() -{ - m_names.Dispose(); - m_object.reset(); - m_index = 0; - m_count = 0; -} - -inline bool QJSValueIteratorPrivate::hasNext() const -{ - return isValid() ? m_index < m_count : false; -} - -inline bool QJSValueIteratorPrivate::next() -{ - if (hasNext()) { - ++m_index; - return true; - } - return false; -} - -inline QString QJSValueIteratorPrivate::name() const -{ - if (!isValid()) - return QString(); - - v8::HandleScope handleScope; - return QJSConverter::toString(m_names->Get(m_index - 1)->ToString()); -} - -inline QScriptPassPointer<QJSValuePrivate> QJSValueIteratorPrivate::value() const -{ - if (!isValid()) - return new QJSValuePrivate(); - - v8::HandleScope handleScope; - return m_object->property(m_names->Get(m_index - 1)->ToString()); -} - -inline bool QJSValueIteratorPrivate::isValid() const -{ - bool result = m_object ? !m_object->isUndefined() : false; - // We know that if this object is still valid then it is an object - // if this assumption is not correct then some other logic in this class - // have to be changed too. - Q_ASSERT(!result || m_object->isObject()); - return result; -} - -inline QV8Engine* QJSValueIteratorPrivate::engine() const -{ - return m_object ? m_object->engine() : 0; -} - -QT_END_NAMESPACE - -#endif // QJSVALUEITERATOR_IMPL_P_H diff --git a/src/qml/qml/v8/qjsvalueiterator_p.h b/src/qml/qml/v8/qjsvalueiterator_p.h index 2d36ac3ca5..999003b41c 100644 --- a/src/qml/qml/v8/qjsvalueiterator_p.h +++ b/src/qml/qml/v8/qjsvalueiterator_p.h @@ -42,10 +42,8 @@ #ifndef QJSVALUEITERATOR_P_H #define QJSVALUEITERATOR_P_H -#include <private/qintrusivelist_p.h> -#include "qjsvalue_p.h" - -#include <private/qv8_p.h> +#include "qjsvalue.h" +#include "private/qv4objectiterator_p.h" QT_BEGIN_NAMESPACE @@ -54,30 +52,18 @@ class QV8Engine; class QJSValueIteratorPrivate { public: - inline QJSValueIteratorPrivate(const QJSValuePrivate* value); - inline ~QJSValueIteratorPrivate(); - - inline bool hasNext() const; - inline bool next(); - - inline QString name() const; - - inline QScriptPassPointer<QJSValuePrivate> value() const; - - inline bool isValid() const; - inline QV8Engine* engine() const; - - inline void invalidate(); -private: - Q_DISABLE_COPY(QJSValueIteratorPrivate) - - QIntrusiveListNode m_node; - QScriptSharedDataPointer<QJSValuePrivate> m_object; - v8::Persistent<v8::Array> m_names; - uint32_t m_index; - uint32_t m_count; - - friend class QV8Engine; + QJSValueIteratorPrivate(const QJSValue &v); + + QJSValue value; + QV4::ObjectIterator iterator; + QV4::Property *currentValue; + QV4::PropertyAttributes currentAttributes; + QV4::String *currentName; + uint currentIndex; + QV4::Property *nextValue; + QV4::PropertyAttributes nextAttributes; + QV4::String *nextName; + uint nextIndex; }; diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp index 457d0bb969..97736355d4 100644 --- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp +++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp @@ -47,12 +47,21 @@ #include <private/qqmlstringconverters_p.h> #include <private/qqmllocale_p.h> #include <private/qv8engine_p.h> -#include <private/qjsconverter_impl_p.h> #include <private/qv8profilerservice_p.h> #include <private/qqmlprofilerservice_p.h> #include <private/qqmlglobal_p.h> +#include <private/qqmlplatform_p.h> + +#include <private/qv4engine_p.h> +#include <private/qv4functionobject_p.h> +#include <private/qv4include_p.h> +#include <private/qv4context_p.h> +#include <private/qv4stringobject_p.h> +#include <private/qv4mm_p.h> +#include <private/qv4jsonobject_p.h> + #include <QtCore/qstring.h> #include <QtCore/qdatetime.h> #include <QtCore/qcryptographichash.h> @@ -65,336 +74,105 @@ QT_BEGIN_NAMESPACE -namespace QQmlBuiltinFunctions { - -enum ConsoleLogTypes { - Log, - Warn, - Error -}; - -static void jsContext(v8::Handle<v8::Value> *file, int *line, v8::Handle<v8::Value> *function) { - v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(1); - if (stackTrace->GetFrameCount()) { - v8::Local<v8::StackFrame> frame = stackTrace->GetFrame(0); - *file = frame->GetScriptName(); - *line = frame->GetLineNumber(); - *function = frame->GetFunctionName(); - } -} - -static QString jsStack() { - QStringList stackFrames; - - //The v8 default is currently 10 stack frames. - v8::Handle<v8::StackTrace> stackTrace = - v8::StackTrace::CurrentStackTrace(10, v8::StackTrace::kOverview); - int stackCount = stackTrace->GetFrameCount(); - - for (int i = 0; i < stackCount; i++) { - v8::Local<v8::StackFrame> frame = stackTrace->GetFrame(i); - v8::Handle<v8::String> function(frame->GetFunctionName()); - v8::Handle<v8::String> script(frame->GetScriptName()); - int lineNumber = frame->GetLineNumber(); - int columnNumber = frame->GetColumn(); - - QString stackFrame = - QString::fromLatin1("%1 (%2:%3:%4)").arg(QJSConverter::toString(function), - QJSConverter::toString(script), - QString::number(lineNumber), - QString::number(columnNumber)); - stackFrames.append(stackFrame); - } - return stackFrames.join(QLatin1String("\n")); -} - -v8::Handle<v8::Value> console(ConsoleLogTypes logType, const v8::Arguments &args, - bool printStack = false) -{ - v8::HandleScope handleScope; - - QString result; - QV8Engine *engine = V8ENGINE(); - for (int i = 0; i < args.Length(); ++i) { - if (i != 0) - result.append(QLatin1Char(' ')); - - v8::Local<v8::Value> value = args[i]; - - v8::TryCatch tryCatch; - v8::Local<v8::String> toString = value->ToString(); - if (tryCatch.HasCaught()) { - // toString() threw Exception - // Is it possible for value to be anything other than Object? - QString str; - if (value->IsObject()) { - str = QStringLiteral("[object Object]"); - } else { - toString = tryCatch.Exception()->ToString(); - str = QStringLiteral("toString() threw exception: %1") - .arg(engine->toString(toString)); - } - result.append(str); - continue; - } - - QString tmp = engine->toString(toString); - if (value->IsArray()) - result.append(QStringLiteral("[%1]").arg(tmp)); - else - result.append(tmp); - } - - if (printStack) { - result.append(QLatin1String("\n")); - result.append(jsStack()); - } - - v8::Handle<v8::Value> fileHandle; - v8::Handle<v8::Value> functionHandle; - int line; - - jsContext(&fileHandle, &line, &functionHandle); - - switch (logType) { - case Log: - QMessageLogger(*v8::String::AsciiValue(fileHandle), line, - *v8::String::AsciiValue(functionHandle)).debug("%s", qPrintable(result)); - break; - case Warn: - QMessageLogger(*v8::String::AsciiValue(fileHandle), line, - *v8::String::AsciiValue(functionHandle)).warning("%s", qPrintable(result)); - break; - case Error: - QMessageLogger(*v8::String::AsciiValue(fileHandle), line, - *v8::String::AsciiValue(functionHandle)).critical("%s", qPrintable(result)); - break; - default: - break; - } +using namespace QV4; - return v8::Undefined(); -} +DEFINE_MANAGED_VTABLE(QtObject); -v8::Handle<v8::Value> gc(const v8::Arguments &args) +struct StaticQtMetaObject : public QObject { - Q_UNUSED(args); - QV8Engine::gc(); - return v8::Undefined(); -} - -v8::Handle<v8::Value> consoleError(const v8::Arguments &args) -{ - return console(Error, args); -} - -v8::Handle<v8::Value> consoleLog(const v8::Arguments &args) -{ - //console.log - //console.debug - //console.info - //print - return console(Log, args); -} + static const QMetaObject *get() + { return &staticQtMetaObject; } +}; -v8::Handle<v8::Value> consoleProfile(const v8::Arguments &args) +QV4::QtObject::QtObject(ExecutionEngine *v4, QQmlEngine *qmlEngine) + : Object(v4) + , m_platform(0) + , m_application(0) { - //DeclarativeDebugTrace cannot handle nested profiling - //although v8 can handle several profiling at once, - //we do not allow that. Hence, we pass an empty(default) title - Q_UNUSED(args); - QString title; - - - - v8::Handle<v8::Value> file; - v8::Handle<v8::Value> function; - int line; - jsContext(&file, &line, &function); - - if (QQmlProfilerService::startProfiling()) { - QV8ProfilerService::instance()->startProfiling(title); - - QMessageLogger(*v8::String::AsciiValue(file), line, - *v8::String::AsciiValue(function)).debug("Profiling started."); - } else { - QMessageLogger(*v8::String::AsciiValue(file), line, - *v8::String::AsciiValue(function)).warning( - "Profiling is already in progress. First, end current profiling session."); + vtbl = &static_vtbl; + + // Set all the enums from the "Qt" namespace + const QMetaObject *qtMetaObject = StaticQtMetaObject::get(); + for (int ii = 0; ii < qtMetaObject->enumeratorCount(); ++ii) { + QMetaEnum enumerator = qtMetaObject->enumerator(ii); + for (int jj = 0; jj < enumerator.keyCount(); ++jj) { + put(v4->newString(enumerator.key(jj)), QV4::Value::fromInt32(enumerator.value(jj))); + } } - - return v8::Undefined(); -} - -v8::Handle<v8::Value> consoleProfileEnd(const v8::Arguments &args) -{ - //DeclarativeDebugTrace cannot handle nested profiling - //although v8 can handle several profiling at once, - //we do not allow that. Hence, we pass an empty(default) title - Q_UNUSED(args); - QString title; - - v8::Handle<v8::Value> file; - v8::Handle<v8::Value> function; - int line; - jsContext(&file, &line, &function); - - if (QQmlProfilerService::stopProfiling()) { - QV8ProfilerService *profiler = QV8ProfilerService::instance(); - profiler->stopProfiling(title); - QQmlProfilerService::sendProfilingData(); - profiler->sendProfilingData(); - - QMessageLogger(*v8::String::AsciiValue(file), line, - *v8::String::AsciiValue(function)).debug("Profiling ended."); - } else { - QMessageLogger(*v8::String::AsciiValue(file), line, - *v8::String::AsciiValue(function)).warning("Profiling was not started."); + put(v4->newString("Asynchronous"), QV4::Value::fromInt32(0)); + put(v4->newString("Synchronous"), QV4::Value::fromInt32(1)); + + defineDefaultProperty(v4, QStringLiteral("include"), QV4Include::include); + defineDefaultProperty(v4, QStringLiteral("isQtObject"), method_isQtObject); + defineDefaultProperty(v4, QStringLiteral("rgba"), method_rgba); + defineDefaultProperty(v4, QStringLiteral("hsla"), method_hsla); + defineDefaultProperty(v4, QStringLiteral("colorEqual"), method_colorEqual); + defineDefaultProperty(v4, QStringLiteral("rect"), method_rect); + defineDefaultProperty(v4, QStringLiteral("point"), method_point); + defineDefaultProperty(v4, QStringLiteral("size"), method_size); + defineDefaultProperty(v4, QStringLiteral("font"), method_font); + + defineDefaultProperty(v4, QStringLiteral("vector2d"), method_vector2d); + defineDefaultProperty(v4, QStringLiteral("vector3d"), method_vector3d); + defineDefaultProperty(v4, QStringLiteral("vector4d"), method_vector4d); + defineDefaultProperty(v4, QStringLiteral("quaternion"), method_quaternion); + defineDefaultProperty(v4, QStringLiteral("matrix4x4"), method_matrix4x4); + + defineDefaultProperty(v4, QStringLiteral("formatDate"), method_formatDate); + defineDefaultProperty(v4, QStringLiteral("formatTime"), method_formatTime); + defineDefaultProperty(v4, QStringLiteral("formatDateTime"), method_formatDateTime); + + defineDefaultProperty(v4, QStringLiteral("openUrlExternally"), method_openUrlExternally); + defineDefaultProperty(v4, QStringLiteral("fontFamilies"), method_fontFamilies); + defineDefaultProperty(v4, QStringLiteral("md5"), method_md5); + defineDefaultProperty(v4, QStringLiteral("btoa"), method_btoa); + defineDefaultProperty(v4, QStringLiteral("atob"), method_atob); + defineDefaultProperty(v4, QStringLiteral("resolvedUrl"), method_resolvedUrl); + defineDefaultProperty(v4, QStringLiteral("locale"), method_locale); + defineDefaultProperty(v4, QStringLiteral("binding"), method_binding); + + if (qmlEngine) { + defineDefaultProperty(v4, QStringLiteral("lighter"), method_lighter); + defineDefaultProperty(v4, QStringLiteral("darker"), method_darker); + defineDefaultProperty(v4, QStringLiteral("tint"), method_tint); + defineDefaultProperty(v4, QStringLiteral("quit"), method_quit); + defineDefaultProperty(v4, QStringLiteral("createQmlObject"), method_createQmlObject); + defineDefaultProperty(v4, QStringLiteral("createComponent"), method_createComponent); } - return v8::Undefined(); -} - -v8::Handle<v8::Value> consoleTime(const v8::Arguments &args) -{ - if (args.Length() != 1) - V8THROW_ERROR("console.time(): Invalid arguments"); - QString name = V8ENGINE()->toString(args[0]); - V8ENGINE()->startTimer(name); - return v8::Undefined(); -} - -v8::Handle<v8::Value> consoleTimeEnd(const v8::Arguments &args) -{ - if (args.Length() != 1) - V8THROW_ERROR("console.time(): Invalid arguments"); - QString name = V8ENGINE()->toString(args[0]); - bool wasRunning; - qint64 elapsed = V8ENGINE()->stopTimer(name, &wasRunning); - if (wasRunning) { - qDebug("%s: %llims", qPrintable(name), elapsed); + { + String *s = v4->newString(QStringLiteral("platform")); + Property *p = insertMember(s, Attr_Accessor); + FunctionObject* f = v4->newBuiltinFunction(v4->rootContext, s, method_get_platform); + p->setGetter(f); } - return v8::Undefined(); -} - -v8::Handle<v8::Value> consoleCount(const v8::Arguments &args) -{ - // first argument: name to print. Ignore any additional arguments - QString name; - if (args.Length() > 0) - name = V8ENGINE()->toString(args[0]); - - v8::Handle<v8::StackTrace> stackTrace = - v8::StackTrace::CurrentStackTrace(1, v8::StackTrace::kOverview); - - if (stackTrace->GetFrameCount()) { - v8::Local<v8::StackFrame> frame = stackTrace->GetFrame(0); - - QString scriptName = V8ENGINE()->toString(frame->GetScriptName()); - QString functionName = V8ENGINE()->toString(frame->GetFunctionName()); - int line = frame->GetLineNumber(); - int column = frame->GetColumn(); - - int value = V8ENGINE()->consoleCountHelper(scriptName, line, column); - QString message = name + QLatin1String(": ") + QString::number(value); - - QMessageLogger(qPrintable(scriptName), line, - qPrintable(functionName)).debug("%s", qPrintable(message)); + { + String *s = v4->newString(QStringLiteral("application")); + Property *p = insertMember(s, Attr_Accessor); + FunctionObject* f = v4->newBuiltinFunction(v4->rootContext, s, method_get_application); + p->setGetter(f); } - - return v8::Undefined(); -} - -v8::Handle<v8::Value> consoleTrace(const v8::Arguments &args) -{ - if (args.Length() != 0) - V8THROW_ERROR("console.trace(): Invalid arguments"); - - QString stack = jsStack(); - - v8::Handle<v8::Value> file; - v8::Handle<v8::Value> function; - int line; - jsContext(&file, &line, &function); - - QMessageLogger(*v8::String::AsciiValue(file), line, *v8::String::AsciiValue(function)).debug( - "%s", qPrintable(stack)); - return v8::Undefined(); -} - -v8::Handle<v8::Value> consoleWarn(const v8::Arguments &args) -{ - return console(Warn, args); -} - -v8::Handle<v8::Value> consoleAssert(const v8::Arguments &args) -{ - if (args.Length() == 0) - V8THROW_ERROR("console.assert(): Missing argument"); - - if (!args[0]->ToBoolean()->Value()) { - QString message; - for (int i = 1; i < args.Length(); ++i) { - if (i != 1) - message.append(QLatin1Char(' ')); - - v8::Local<v8::Value> value = args[i]; - message.append(V8ENGINE()->toString(value->ToString())); - } - - QString stack = jsStack(); - - v8::Handle<v8::Value> file; - v8::Handle<v8::Value> function; - int line; - jsContext(&file, &line, &function); - - QMessageLogger(*v8::String::AsciiValue(file), line, *v8::String::AsciiValue(function)).critical( - "%s\n%s", qPrintable(message), qPrintable(stack)); - +#ifndef QT_NO_IM + { + String *s = v4->newString(QStringLiteral("inputMethod")); + Property *p = insertMember(s, Attr_Accessor); + FunctionObject* f = v4->newBuiltinFunction(v4->rootContext, s, method_get_inputMethod); + p->setGetter(f); } - return v8::Undefined(); -} - -v8::Handle<v8::Value> consoleException(const v8::Arguments &args) -{ - if (args.Length() == 0) - V8THROW_ERROR("console.exception(): Missing argument"); - - console(Error, args, true); - - return v8::Undefined(); +#endif } -v8::Handle<v8::Value> stringArg(const v8::Arguments &args) -{ - QString value = V8ENGINE()->toString(args.This()->ToString()); - if (args.Length() != 1) - V8THROW_ERROR("String.arg(): Invalid arguments"); - - v8::Handle<v8::Value> arg = args[0]; - if (arg->IsUint32()) - return V8ENGINE()->toString(value.arg(arg->Uint32Value())); - else if (arg->IsInt32()) - return V8ENGINE()->toString(value.arg(arg->Int32Value())); - else if (arg->IsNumber()) - return V8ENGINE()->toString(value.arg(arg->NumberValue())); - else if (arg->IsBoolean()) - return V8ENGINE()->toString(value.arg(arg->BooleanValue())); - - return V8ENGINE()->toString(value.arg(V8ENGINE()->toString(arg))); -} /*! \qmlmethod bool Qt::isQtObject(object) Returns true if \c object is a valid reference to a Qt or QML object, otherwise false. */ -v8::Handle<v8::Value> isQtObject(const v8::Arguments &args) +Value QtObject::method_isQtObject(QV4::SimpleCallContext *ctx) { - if (args.Length() == 0) - return v8::Boolean::New(false); + if (ctx->argumentCount == 0) + return QV4::Value::fromBoolean(false); - return v8::Boolean::New(0 != V8ENGINE()->toQObject(args[0])); + return QV4::Value::fromBoolean(ctx->arguments[0].as<QV4::QObjectWrapper>() != 0); } /*! @@ -403,16 +181,16 @@ v8::Handle<v8::Value> isQtObject(const v8::Arguments &args) Returns a color with the specified \c red, \c green, \c blue and \c alpha components. All components should be in the range 0-1 inclusive. */ -v8::Handle<v8::Value> rgba(const v8::Arguments &args) +Value QtObject::method_rgba(QV4::SimpleCallContext *ctx) { - int argCount = args.Length(); + int argCount = ctx->argumentCount; if (argCount < 3 || argCount > 4) - V8THROW_ERROR("Qt.rgba(): Invalid arguments"); + V4THROW_ERROR("Qt.rgba(): Invalid arguments"); - double r = args[0]->NumberValue(); - double g = args[1]->NumberValue(); - double b = args[2]->NumberValue(); - double a = (argCount == 4) ? args[3]->NumberValue() : 1; + double r = ctx->arguments[0].toNumber(); + double g = ctx->arguments[1].toNumber(); + double b = ctx->arguments[2].toNumber(); + double a = (argCount == 4) ? ctx->arguments[3].toNumber() : 1; if (r < 0.0) r=0.0; if (r > 1.0) r=1.0; @@ -423,7 +201,7 @@ v8::Handle<v8::Value> rgba(const v8::Arguments &args) if (a < 0.0) a=0.0; if (a > 1.0) a=1.0; - return V8ENGINE()->fromVariant(QQml_colorProvider()->fromRgbF(r, g, b, a)); + return ctx->engine->v8Engine->fromVariant(QQml_colorProvider()->fromRgbF(r, g, b, a)); } /*! @@ -432,16 +210,16 @@ v8::Handle<v8::Value> rgba(const v8::Arguments &args) Returns a color with the specified \c hue, \c saturation, \c lightness and \c alpha components. All components should be in the range 0-1 inclusive. */ -v8::Handle<v8::Value> hsla(const v8::Arguments &args) +Value QtObject::method_hsla(QV4::SimpleCallContext *ctx) { - int argCount = args.Length(); + int argCount = ctx->argumentCount; if (argCount < 3 || argCount > 4) - V8THROW_ERROR("Qt.hsla(): Invalid arguments"); + V4THROW_ERROR("Qt.hsla(): Invalid arguments"); - double h = args[0]->NumberValue(); - double s = args[1]->NumberValue(); - double l = args[2]->NumberValue(); - double a = (argCount == 4) ? args[3]->NumberValue() : 1; + double h = ctx->arguments[0].toNumber(); + double s = ctx->arguments[1].toNumber(); + double l = ctx->arguments[2].toNumber(); + double a = (argCount == 4) ? ctx->arguments[3].toNumber() : 1; if (h < 0.0) h=0.0; if (h > 1.0) h=1.0; @@ -452,7 +230,7 @@ v8::Handle<v8::Value> hsla(const v8::Arguments &args) if (a < 0.0) a=0.0; if (a > 1.0) a=1.0; - return V8ENGINE()->fromVariant(QQml_colorProvider()->fromHslF(h, s, l, a)); + return ctx->engine->v8Engine->fromVariant(QQml_colorProvider()->fromHslF(h, s, l, a)); } /*! @@ -463,35 +241,37 @@ may be either color values or string values. If a string value is supplied it must be convertible to a color, as described for the \l{colorbasictypedocs}{color} basic type. */ -v8::Handle<v8::Value> colorEqual(const v8::Arguments &args) +Value QtObject::method_colorEqual(QV4::SimpleCallContext *ctx) { - if (args.Length() != 2) - V8THROW_ERROR("Qt.colorEqual(): Invalid arguments"); + if (ctx->argumentCount != 2) + V4THROW_ERROR("Qt.colorEqual(): Invalid arguments"); bool ok = false; - QVariant lhs = V8ENGINE()->toVariant(args[0], -1); + QV8Engine *v8engine = ctx->engine->v8Engine; + + QVariant lhs = v8engine->toVariant(ctx->arguments[0], -1); if (lhs.userType() == QVariant::String) { lhs = QQmlStringConverters::colorFromString(lhs.toString(), &ok); if (!ok) { - V8THROW_ERROR("Qt.colorEqual(): Invalid color name"); + V4THROW_ERROR("Qt.colorEqual(): Invalid color name"); } } else if (lhs.userType() != QVariant::Color) { - V8THROW_ERROR("Qt.colorEqual(): Invalid arguments"); + V4THROW_ERROR("Qt.colorEqual(): Invalid arguments"); } - QVariant rhs = V8ENGINE()->toVariant(args[1], -1); + QVariant rhs = v8engine->toVariant(ctx->arguments[1], -1); if (rhs.userType() == QVariant::String) { rhs = QQmlStringConverters::colorFromString(rhs.toString(), &ok); if (!ok) { - V8THROW_ERROR("Qt.colorEqual(): Invalid color name"); + V4THROW_ERROR("Qt.colorEqual(): Invalid color name"); } } else if (rhs.userType() != QVariant::Color) { - V8THROW_ERROR("Qt.colorEqual(): Invalid arguments"); + V4THROW_ERROR("Qt.colorEqual(): Invalid arguments"); } bool equal = (lhs == rhs); - return V8ENGINE()->fromVariant(equal); + return QV4::Value::fromBoolean(equal); } /*! @@ -501,141 +281,147 @@ Returns a \c rect with the top-left corner at \c x, \c y and the specified \c wi The returned object has \c x, \c y, \c width and \c height attributes with the given values. */ -v8::Handle<v8::Value> rect(const v8::Arguments &args) +Value QtObject::method_rect(QV4::SimpleCallContext *ctx) { - if (args.Length() != 4) - V8THROW_ERROR("Qt.rect(): Invalid arguments"); + if (ctx->argumentCount != 4) + V4THROW_ERROR("Qt.rect(): Invalid arguments"); - double x = args[0]->NumberValue(); - double y = args[1]->NumberValue(); - double w = args[2]->NumberValue(); - double h = args[3]->NumberValue(); + double x = ctx->arguments[0].toNumber(); + double y = ctx->arguments[1].toNumber(); + double w = ctx->arguments[2].toNumber(); + double h = ctx->arguments[3].toNumber(); - return V8ENGINE()->fromVariant(QVariant::fromValue(QRectF(x, y, w, h))); + return ctx->engine->v8Engine->fromVariant(QVariant::fromValue(QRectF(x, y, w, h))); } /*! \qmlmethod point Qt::point(int x, int y) Returns a Point with the specified \c x and \c y coordinates. */ -v8::Handle<v8::Value> point(const v8::Arguments &args) +Value QtObject::method_point(QV4::SimpleCallContext *ctx) { - if (args.Length() != 2) - V8THROW_ERROR("Qt.point(): Invalid arguments"); + if (ctx->argumentCount != 2) + V4THROW_ERROR("Qt.point(): Invalid arguments"); - double x = args[0]->ToNumber()->Value(); - double y = args[1]->ToNumber()->Value(); + double x = ctx->arguments[0].toNumber(); + double y = ctx->arguments[1].toNumber(); - return V8ENGINE()->fromVariant(QVariant::fromValue(QPointF(x, y))); + return ctx->engine->v8Engine->fromVariant(QVariant::fromValue(QPointF(x, y))); } /*! \qmlmethod Qt::size(int width, int height) Returns a Size with the specified \c width and \c height. */ -v8::Handle<v8::Value> size(const v8::Arguments &args) +Value QtObject::method_size(QV4::SimpleCallContext *ctx) { - if (args.Length() != 2) - V8THROW_ERROR("Qt.size(): Invalid arguments"); + if (ctx->argumentCount != 2) + V4THROW_ERROR("Qt.size(): Invalid arguments"); - double w = args[0]->ToNumber()->Value(); - double h = args[1]->ToNumber()->Value(); + double w = ctx->arguments[0].toNumber(); + double h = ctx->arguments[1].toNumber(); - return V8ENGINE()->fromVariant(QVariant::fromValue(QSizeF(w, h))); + return ctx->engine->v8Engine->fromVariant(QVariant::fromValue(QSizeF(w, h))); } /*! +\qmlmethod Qt::font(object fontSpecifier) +Returns a Font with the properties specified in the \c fontSpecifier object +or the nearest matching font. The \c fontSpecifier object should contain +key-value pairs where valid keys are the \l{fontbasictypedocs}{font} type's +subproperty names, and the values are valid values for each subproperty. +Invalid keys will be ignored. +*/ +Value QtObject::method_font(QV4::SimpleCallContext *ctx) +{ + if (ctx->argumentCount != 1 || !ctx->arguments[0].isObject()) + V4THROW_ERROR("Qt.font(): Invalid arguments"); + + QV8Engine *v8engine = ctx->engine->v8Engine; + bool ok = false; + QVariant v = QQml_valueTypeProvider()->createVariantFromJsObject(QMetaType::QFont, QQmlV4Handle(ctx->arguments[0]), v8engine, &ok); + if (!ok) + V4THROW_ERROR("Qt.font(): Invalid argument: no valid font subproperties specified"); + return v8engine->fromVariant(v); +} + + + +/*! \qmlmethod Qt::vector2d(real x, real y) Returns a Vector2D with the specified \c x and \c y. */ -v8::Handle<v8::Value> vector2d(const v8::Arguments &args) +Value QtObject::method_vector2d(QV4::SimpleCallContext *ctx) { - if (args.Length() != 2) - V8THROW_ERROR("Qt.vector2d(): Invalid arguments"); + if (ctx->argumentCount != 2) + V4THROW_ERROR("Qt.vector2d(): Invalid arguments"); float xy[3]; // qvector2d uses float internally - xy[0] = args[0]->ToNumber()->Value(); - xy[1] = args[1]->ToNumber()->Value(); + xy[0] = ctx->arguments[0].toNumber(); + xy[1] = ctx->arguments[1].toNumber(); const void *params[] = { xy }; - return V8ENGINE()->fromVariant(QQml_valueTypeProvider()->createValueType(QMetaType::QVector2D, 1, params)); + QV8Engine *v8engine = ctx->engine->v8Engine; + return v8engine->fromVariant(QQml_valueTypeProvider()->createValueType(QMetaType::QVector2D, 1, params)); } /*! \qmlmethod Qt::vector3d(real x, real y, real z) Returns a Vector3D with the specified \c x, \c y and \c z. */ -v8::Handle<v8::Value> vector3d(const v8::Arguments &args) +Value QtObject::method_vector3d(QV4::SimpleCallContext *ctx) { - if (args.Length() != 3) - V8THROW_ERROR("Qt.vector3d(): Invalid arguments"); + if (ctx->argumentCount != 3) + V4THROW_ERROR("Qt.vector3d(): Invalid arguments"); float xyz[3]; // qvector3d uses float internally - xyz[0] = args[0]->ToNumber()->Value(); - xyz[1] = args[1]->ToNumber()->Value(); - xyz[2] = args[2]->ToNumber()->Value(); + xyz[0] = ctx->arguments[0].toNumber(); + xyz[1] = ctx->arguments[1].toNumber(); + xyz[2] = ctx->arguments[2].toNumber(); const void *params[] = { xyz }; - return V8ENGINE()->fromVariant(QQml_valueTypeProvider()->createValueType(QMetaType::QVector3D, 1, params)); + QV8Engine *v8engine = ctx->engine->v8Engine; + return v8engine->fromVariant(QQml_valueTypeProvider()->createValueType(QMetaType::QVector3D, 1, params)); } /*! \qmlmethod Qt::vector4d(real x, real y, real z, real w) Returns a Vector4D with the specified \c x, \c y, \c z and \c w. */ -v8::Handle<v8::Value> vector4d(const v8::Arguments &args) +Value QtObject::method_vector4d(QV4::SimpleCallContext *ctx) { - if (args.Length() != 4) - V8THROW_ERROR("Qt.vector4d(): Invalid arguments"); + if (ctx->argumentCount != 4) + V4THROW_ERROR("Qt.vector4d(): Invalid arguments"); float xyzw[4]; // qvector4d uses float internally - xyzw[0] = args[0]->ToNumber()->Value(); - xyzw[1] = args[1]->ToNumber()->Value(); - xyzw[2] = args[2]->ToNumber()->Value(); - xyzw[3] = args[3]->ToNumber()->Value(); + xyzw[0] = ctx->arguments[0].toNumber(); + xyzw[1] = ctx->arguments[1].toNumber(); + xyzw[2] = ctx->arguments[2].toNumber(); + xyzw[3] = ctx->arguments[3].toNumber(); const void *params[] = { xyzw }; - return V8ENGINE()->fromVariant(QQml_valueTypeProvider()->createValueType(QMetaType::QVector4D, 1, params)); + QV8Engine *v8engine = ctx->engine->v8Engine; + return v8engine->fromVariant(QQml_valueTypeProvider()->createValueType(QMetaType::QVector4D, 1, params)); } /*! \qmlmethod Qt::quaternion(real scalar, real x, real y, real z) Returns a Quaternion with the specified \c scalar, \c x, \c y, and \c z. */ -v8::Handle<v8::Value> quaternion(const v8::Arguments &args) +Value QtObject::method_quaternion(QV4::SimpleCallContext *ctx) { - if (args.Length() != 4) - V8THROW_ERROR("Qt.quaternion(): Invalid arguments"); + if (ctx->argumentCount != 4) + V4THROW_ERROR("Qt.quaternion(): Invalid arguments"); qreal sxyz[4]; // qquaternion uses qreal internally - sxyz[0] = args[0]->ToNumber()->Value(); - sxyz[1] = args[1]->ToNumber()->Value(); - sxyz[2] = args[2]->ToNumber()->Value(); - sxyz[3] = args[3]->ToNumber()->Value(); + sxyz[0] = ctx->arguments[0].toNumber(); + sxyz[1] = ctx->arguments[1].toNumber(); + sxyz[2] = ctx->arguments[2].toNumber(); + sxyz[3] = ctx->arguments[3].toNumber(); const void *params[] = { sxyz }; - return V8ENGINE()->fromVariant(QQml_valueTypeProvider()->createValueType(QMetaType::QQuaternion, 1, params)); -} - -/*! -\qmlmethod Qt::font(object fontSpecifier) -Returns a Font with the properties specified in the \c fontSpecifier object -or the nearest matching font. The \c fontSpecifier object should contain -key-value pairs where valid keys are the \l{fontbasictypedocs}{font} type's -subproperty names, and the values are valid values for each subproperty. -Invalid keys will be ignored. -*/ -v8::Handle<v8::Value> font(const v8::Arguments &args) -{ - if (args.Length() != 1 || !args[0]->IsObject()) - V8THROW_ERROR("Qt.font(): Invalid arguments"); - - v8::Handle<v8::Object> obj = args[0]->ToObject(); - bool ok = false; - QVariant v = QQml_valueTypeProvider()->createVariantFromJsObject(QMetaType::QFont, QQmlV8Handle::fromHandle(obj), V8ENGINE(), &ok); - if (!ok) - V8THROW_ERROR("Qt.font(): Invalid argument: no valid font subproperties specified"); - return V8ENGINE()->fromVariant(v); + QV8Engine *v8engine = ctx->engine->v8Engine; + return v8engine->fromVariant(QQml_valueTypeProvider()->createValueType(QMetaType::QQuaternion, 1, params)); } /*! @@ -645,40 +431,41 @@ Alternatively, the function may be called with a single argument where that argument is a JavaScript array which contains the sixteen matrix values. */ -v8::Handle<v8::Value> matrix4x4(const v8::Arguments &args) +Value QtObject::method_matrix4x4(QV4::SimpleCallContext *ctx) { - if (args.Length() == 1 && args[0]->IsObject()) { - v8::Handle<v8::Object> obj = args[0]->ToObject(); + QV8Engine *v8engine = ctx->engine->v8Engine; + + if (ctx->argumentCount == 1 && ctx->arguments[0].isObject()) { bool ok = false; - QVariant v = QQml_valueTypeProvider()->createVariantFromJsObject(QMetaType::QMatrix4x4, QQmlV8Handle::fromHandle(obj), V8ENGINE(), &ok); + QVariant v = QQml_valueTypeProvider()->createVariantFromJsObject(QMetaType::QMatrix4x4, QQmlV4Handle(ctx->arguments[0]), v8engine, &ok); if (!ok) - V8THROW_ERROR("Qt.matrix4x4(): Invalid argument: not a valid matrix4x4 values array"); - return V8ENGINE()->fromVariant(v); + V4THROW_ERROR("Qt.matrix4x4(): Invalid argument: not a valid matrix4x4 values array"); + return v8engine->fromVariant(v); } - if (args.Length() != 16) - V8THROW_ERROR("Qt.matrix4x4(): Invalid arguments"); + if (ctx->argumentCount != 16) + V4THROW_ERROR("Qt.matrix4x4(): Invalid arguments"); qreal vals[16]; // qmatrix4x4 uses qreal internally - vals[0] = args[0]->ToNumber()->Value(); - vals[1] = args[1]->ToNumber()->Value(); - vals[2] = args[2]->ToNumber()->Value(); - vals[3] = args[3]->ToNumber()->Value(); - vals[4] = args[4]->ToNumber()->Value(); - vals[5] = args[5]->ToNumber()->Value(); - vals[6] = args[6]->ToNumber()->Value(); - vals[7] = args[7]->ToNumber()->Value(); - vals[8] = args[8]->ToNumber()->Value(); - vals[9] = args[9]->ToNumber()->Value(); - vals[10] = args[10]->ToNumber()->Value(); - vals[11] = args[11]->ToNumber()->Value(); - vals[12] = args[12]->ToNumber()->Value(); - vals[13] = args[13]->ToNumber()->Value(); - vals[14] = args[14]->ToNumber()->Value(); - vals[15] = args[15]->ToNumber()->Value(); + vals[0] = ctx->arguments[0].toNumber(); + vals[1] = ctx->arguments[1].toNumber(); + vals[2] = ctx->arguments[2].toNumber(); + vals[3] = ctx->arguments[3].toNumber(); + vals[4] = ctx->arguments[4].toNumber(); + vals[5] = ctx->arguments[5].toNumber(); + vals[6] = ctx->arguments[6].toNumber(); + vals[7] = ctx->arguments[7].toNumber(); + vals[8] = ctx->arguments[8].toNumber(); + vals[9] = ctx->arguments[9].toNumber(); + vals[10] = ctx->arguments[10].toNumber(); + vals[11] = ctx->arguments[11].toNumber(); + vals[12] = ctx->arguments[12].toNumber(); + vals[13] = ctx->arguments[13].toNumber(); + vals[14] = ctx->arguments[14].toNumber(); + vals[15] = ctx->arguments[15].toNumber(); const void *params[] = { vals }; - return V8ENGINE()->fromVariant(QQml_valueTypeProvider()->createValueType(QMetaType::QMatrix4x4, 1, params)); + return v8engine->fromVariant(QQml_valueTypeProvider()->createValueType(QMetaType::QMatrix4x4, 1, params)); } /*! @@ -695,27 +482,28 @@ by factor and converts the color back to RGB. If \c factor is not supplied, returns a color 50% lighter than \c baseColor (factor 1.5). */ -v8::Handle<v8::Value> lighter(const v8::Arguments &args) +Value QtObject::method_lighter(QV4::SimpleCallContext *ctx) { - if (args.Length() != 1 && args.Length() != 2) - V8THROW_ERROR("Qt.lighter(): Invalid arguments"); + if (ctx->argumentCount != 1 && ctx->argumentCount != 2) + V4THROW_ERROR("Qt.lighter(): Invalid arguments"); - QVariant v = V8ENGINE()->toVariant(args[0], -1); + QV8Engine *v8engine = ctx->engine->v8Engine; + QVariant v = v8engine->toVariant(ctx->arguments[0], -1); if (v.userType() == QVariant::String) { bool ok = false; v = QQmlStringConverters::colorFromString(v.toString(), &ok); if (!ok) { - return v8::Null(); + return QV4::Value::nullValue(); } } else if (v.userType() != QVariant::Color) { - return v8::Null(); + return QV4::Value::nullValue(); } qreal factor = 1.5; - if (args.Length() == 2) - factor = args[1]->ToNumber()->Value(); + if (ctx->argumentCount == 2) + factor = ctx->arguments[1].toNumber(); - return V8ENGINE()->fromVariant(QQml_colorProvider()->lighter(v, factor)); + return v8engine->fromVariant(QQml_colorProvider()->lighter(v, factor)); } /*! @@ -733,27 +521,28 @@ by factor and converts the color back to RGB. If \c factor is not supplied, returns a color 50% darker than \c baseColor (factor 2.0). */ -v8::Handle<v8::Value> darker(const v8::Arguments &args) +Value QtObject::method_darker(QV4::SimpleCallContext *ctx) { - if (args.Length() != 1 && args.Length() != 2) - V8THROW_ERROR("Qt.darker(): Invalid arguments"); + if (ctx->argumentCount != 1 && ctx->argumentCount != 2) + V4THROW_ERROR("Qt.darker(): Invalid arguments"); - QVariant v = V8ENGINE()->toVariant(args[0], -1); + QV8Engine *v8engine = ctx->engine->v8Engine; + QVariant v = v8engine->toVariant(ctx->arguments[0], -1); if (v.userType() == QVariant::String) { bool ok = false; v = QQmlStringConverters::colorFromString(v.toString(), &ok); if (!ok) { - return v8::Null(); + return QV4::Value::nullValue(); } } else if (v.userType() != QVariant::Color) { - return v8::Null(); + return QV4::Value::nullValue(); } qreal factor = 2.0; - if (args.Length() == 2) - factor = args[1]->ToNumber()->Value(); + if (ctx->argumentCount == 2) + factor = ctx->arguments[1].toNumber(); - return V8ENGINE()->fromVariant(QQml_colorProvider()->darker(v, factor)); + return v8engine->fromVariant(QQml_colorProvider()->darker(v, factor)); } /*! @@ -780,36 +569,38 @@ v8::Handle<v8::Value> darker(const v8::Arguments &args) Tint is most useful when a subtle change is intended to be conveyed due to some event; you can then use tinting to more effectively tune the visible color. */ -v8::Handle<v8::Value> tint(const v8::Arguments &args) +Value QtObject::method_tint(QV4::SimpleCallContext *ctx) { - if (args.Length() != 2) - V8THROW_ERROR("Qt.tint(): Invalid arguments"); + if (ctx->argumentCount != 2) + V4THROW_ERROR("Qt.tint(): Invalid arguments"); + + QV8Engine *v8engine = ctx->engine->v8Engine; // base color - QVariant v1 = V8ENGINE()->toVariant(args[0], -1); + QVariant v1 = v8engine->toVariant(ctx->arguments[0], -1); if (v1.userType() == QVariant::String) { bool ok = false; v1 = QQmlStringConverters::colorFromString(v1.toString(), &ok); if (!ok) { - return v8::Null(); + return QV4::Value::nullValue(); } } else if (v1.userType() != QVariant::Color) { - return v8::Null(); + return QV4::Value::nullValue(); } // tint color - QVariant v2 = V8ENGINE()->toVariant(args[1], -1); + QVariant v2 = v8engine->toVariant(ctx->arguments[1], -1); if (v2.userType() == QVariant::String) { bool ok = false; v2 = QQmlStringConverters::colorFromString(v2.toString(), &ok); if (!ok) { - return v8::Null(); + return QV4::Value::nullValue(); } } else if (v2.userType() != QVariant::Color) { - return v8::Null(); + return QV4::Value::nullValue(); } - return V8ENGINE()->fromVariant(QQml_colorProvider()->tint(v1, v2)); + return v8engine->fromVariant(QQml_colorProvider()->tint(v1, v2)); } /*! @@ -828,30 +619,32 @@ If \a format is not specified, \a date is formatted using \sa Locale */ -v8::Handle<v8::Value> formatDate(const v8::Arguments &args) +Value QtObject::method_formatDate(QV4::SimpleCallContext *ctx) { - if (args.Length() < 1 || args.Length() > 2) - V8THROW_ERROR("Qt.formatDate(): Invalid arguments"); + if (ctx->argumentCount < 1 || ctx->argumentCount > 2) + V4THROW_ERROR("Qt.formatDate(): Invalid arguments"); + + QV8Engine *v8engine = ctx->engine->v8Engine; Qt::DateFormat enumFormat = Qt::DefaultLocaleShortDate; - QDate date = V8ENGINE()->toVariant(args[0], -1).toDateTime().date(); + QDate date = v8engine->toVariant(ctx->arguments[0], -1).toDateTime().date(); QString formattedDate; - if (args.Length() == 2) { - if (args[1]->IsString()) { - QString format = V8ENGINE()->toVariant(args[1], -1).toString(); + if (ctx->argumentCount == 2) { + if (String *s = ctx->arguments[1].asString()) { + QString format = s->toQString(); formattedDate = date.toString(format); - } else if (args[1]->IsNumber()) { - quint32 intFormat = args[1]->ToNumber()->Value(); + } else if (ctx->arguments[1].isNumber()) { + quint32 intFormat = ctx->arguments[1].asDouble(); Qt::DateFormat format = Qt::DateFormat(intFormat); formattedDate = date.toString(format); } else { - V8THROW_ERROR("Qt.formatDate(): Invalid date format"); + V4THROW_ERROR("Qt.formatDate(): Invalid date format"); } } else { formattedDate = date.toString(enumFormat); } - return V8ENGINE()->fromVariant(QVariant::fromValue(formattedDate)); + return v8engine->fromVariant(QVariant::fromValue(formattedDate)); } /*! @@ -869,36 +662,38 @@ If \a format is not specified, \a time is formatted using \sa Locale */ -v8::Handle<v8::Value> formatTime(const v8::Arguments &args) +Value QtObject::method_formatTime(QV4::SimpleCallContext *ctx) { - if (args.Length() < 1 || args.Length() > 2) - V8THROW_ERROR("Qt.formatTime(): Invalid arguments"); + if (ctx->argumentCount < 1 || ctx->argumentCount > 2) + V4THROW_ERROR("Qt.formatTime(): Invalid arguments"); - QVariant argVariant = V8ENGINE()->toVariant(args[0], -1); + QV8Engine *v8engine = ctx->engine->v8Engine; + + QVariant argVariant = v8engine->toVariant(ctx->arguments[0], -1); QTime time; - if (args[0]->IsDate() || (argVariant.type() == QVariant::String)) + if (ctx->arguments[0].asDateObject() || (argVariant.type() == QVariant::String)) time = argVariant.toDateTime().time(); else // if (argVariant.type() == QVariant::Time), or invalid. time = argVariant.toTime(); Qt::DateFormat enumFormat = Qt::DefaultLocaleShortDate; QString formattedTime; - if (args.Length() == 2) { - if (args[1]->IsString()) { - QString format = V8ENGINE()->toVariant(args[1], -1).toString(); + if (ctx->argumentCount == 2) { + if (String *s = ctx->arguments[1].asString()) { + QString format = s->toQString(); formattedTime = time.toString(format); - } else if (args[1]->IsNumber()) { - quint32 intFormat = args[1]->ToNumber()->Value(); + } else if (ctx->arguments[1].isNumber()) { + quint32 intFormat = ctx->arguments[1].asDouble(); Qt::DateFormat format = Qt::DateFormat(intFormat); formattedTime = time.toString(format); } else { - V8THROW_ERROR("Qt.formatTime(): Invalid time format"); + V4THROW_ERROR("Qt.formatTime(): Invalid time format"); } } else { formattedTime = time.toString(enumFormat); } - return V8ENGINE()->fromVariant(QVariant::fromValue(formattedTime)); + return v8engine->fromVariant(QVariant::fromValue(formattedTime)); } /*! @@ -991,118 +786,125 @@ with the \a format values below to produce the following results: \sa Locale */ -v8::Handle<v8::Value> formatDateTime(const v8::Arguments &args) +Value QtObject::method_formatDateTime(QV4::SimpleCallContext *ctx) { - if (args.Length() < 1 || args.Length() > 2) - V8THROW_ERROR("Qt.formatDateTime(): Invalid arguments"); + if (ctx->argumentCount < 1 || ctx->argumentCount > 2) + V4THROW_ERROR("Qt.formatDateTime(): Invalid arguments"); + + QV8Engine *v8engine = ctx->engine->v8Engine; Qt::DateFormat enumFormat = Qt::DefaultLocaleShortDate; - QDateTime dt = V8ENGINE()->toVariant(args[0], -1).toDateTime(); + QDateTime dt = v8engine->toVariant(ctx->arguments[0], -1).toDateTime(); QString formattedDt; - if (args.Length() == 2) { - if (args[1]->IsString()) { - QString format = V8ENGINE()->toVariant(args[1], -1).toString(); + if (ctx->argumentCount == 2) { + if (String *s = ctx->arguments[1].asString()) { + QString format = s->toQString(); formattedDt = dt.toString(format); - } else if (args[1]->IsNumber()) { - quint32 intFormat = args[1]->ToNumber()->Value(); + } else if (ctx->arguments[1].isNumber()) { + quint32 intFormat = ctx->arguments[1].asDouble(); Qt::DateFormat format = Qt::DateFormat(intFormat); formattedDt = dt.toString(format); } else { - V8THROW_ERROR("Qt.formatDateTime(): Invalid datetime format"); + V4THROW_ERROR("Qt.formatDateTime(): Invalid datetime format"); } } else { formattedDt = dt.toString(enumFormat); } - return V8ENGINE()->fromVariant(QVariant::fromValue(formattedDt)); + return v8engine->fromVariant(QVariant::fromValue(formattedDt)); } /*! \qmlmethod bool Qt::openUrlExternally(url target) Attempts to open the specified \c target url in an external application, based on the user's desktop preferences. Returns true if it succeeds, and false otherwise. */ -v8::Handle<v8::Value> openUrlExternally(const v8::Arguments &args) +Value QtObject::method_openUrlExternally(QV4::SimpleCallContext *ctx) { - if (args.Length() != 1) - return V8ENGINE()->fromVariant(false); + if (ctx->argumentCount != 1) + return QV4::Value::fromBoolean(false); - QUrl url(V8ENGINE()->toVariant(resolvedUrl(args), -1).toUrl()); - return V8ENGINE()->fromVariant(QQml_guiProvider()->openUrlExternally(url)); + QV8Engine *v8engine = ctx->engine->v8Engine; + + QUrl url(method_resolvedUrl(ctx).toQString()); + return v8engine->fromVariant(QQml_guiProvider()->openUrlExternally(url)); } /*! \qmlmethod url Qt::resolvedUrl(url url) Returns \a url resolved relative to the URL of the caller. */ -v8::Handle<v8::Value> resolvedUrl(const v8::Arguments &args) +Value QtObject::method_resolvedUrl(QV4::SimpleCallContext *ctx) { - QUrl url = V8ENGINE()->toVariant(args[0], -1).toUrl(); - QQmlEngine *e = V8ENGINE()->engine(); + QV8Engine *v8engine = ctx->engine->v8Engine; + + QUrl url = v8engine->toVariant(ctx->arguments[0], -1).toUrl(); + QQmlEngine *e = v8engine->engine(); QQmlEnginePrivate *p = 0; if (e) p = QQmlEnginePrivate::get(e); if (p) { - QQmlContextData *ctxt = V8ENGINE()->callingContext(); + QQmlContextData *ctxt = v8engine->callingContext(); if (ctxt) - return V8ENGINE()->toString(ctxt->resolvedUrl(url).toString()); + return Value::fromString(ctx, ctxt->resolvedUrl(url).toString()); else - return V8ENGINE()->toString(url.toString()); + return Value::fromString(ctx, url.toString()); } - return V8ENGINE()->toString(e->baseUrl().resolved(url).toString()); + return Value::fromString(ctx, e->baseUrl().resolved(url).toString()); } /*! \qmlmethod list<string> Qt::fontFamilies() Returns a list of the font families available to the application. */ -v8::Handle<v8::Value> fontFamilies(const v8::Arguments &args) +Value QtObject::method_fontFamilies(SimpleCallContext *ctx) { - if (args.Length() != 0) - V8THROW_ERROR("Qt.fontFamilies(): Invalid arguments"); + if (ctx->argumentCount != 0) + V4THROW_ERROR("Qt.fontFamilies(): Invalid arguments"); - return V8ENGINE()->fromVariant(QVariant(QQml_guiProvider()->fontFamilies())); + QV8Engine *v8engine = ctx->engine->v8Engine; + return v8engine->fromVariant(QVariant(QQml_guiProvider()->fontFamilies())); } /*! \qmlmethod string Qt::md5(data) Returns a hex string of the md5 hash of \c data. */ -v8::Handle<v8::Value> md5(const v8::Arguments &args) +Value QtObject::method_md5(SimpleCallContext *ctx) { - if (args.Length() != 1) - V8THROW_ERROR("Qt.md5(): Invalid arguments"); + if (ctx->argumentCount != 1) + V4THROW_ERROR("Qt.md5(): Invalid arguments"); - QByteArray data = V8ENGINE()->toString(args[0]->ToString()).toUtf8(); + QByteArray data = ctx->arguments[0].toQString().toUtf8(); QByteArray result = QCryptographicHash::hash(data, QCryptographicHash::Md5); - return V8ENGINE()->toString(QLatin1String(result.toHex())); + return Value::fromString(ctx, QLatin1String(result.toHex())); } /*! \qmlmethod string Qt::btoa(data) Binary to ASCII - this function returns a base64 encoding of \c data. */ -v8::Handle<v8::Value> btoa(const v8::Arguments &args) +Value QtObject::method_btoa(SimpleCallContext *ctx) { - if (args.Length() != 1) - V8THROW_ERROR("Qt.btoa(): Invalid arguments"); + if (ctx->argumentCount != 1) + V4THROW_ERROR("Qt.btoa(): Invalid arguments"); - QByteArray data = V8ENGINE()->toString(args[0]->ToString()).toUtf8(); + QByteArray data = ctx->arguments[0].toQString().toUtf8(); - return V8ENGINE()->toString(QLatin1String(data.toBase64())); + return Value::fromString(ctx, QLatin1String(data.toBase64())); } /*! \qmlmethod string Qt::atob(data) ASCII to binary - this function returns a base64 decoding of \c data. */ -v8::Handle<v8::Value> atob(const v8::Arguments &args) +Value QtObject::method_atob(SimpleCallContext *ctx) { - if (args.Length() != 1) - V8THROW_ERROR("Qt.atob(): Invalid arguments"); + if (ctx->argumentCount != 1) + V4THROW_ERROR("Qt.atob(): Invalid arguments"); - QByteArray data = V8ENGINE()->toString(args[0]->ToString()).toUtf8(); + QByteArray data = ctx->arguments[0].toQString().toLatin1(); - return V8ENGINE()->toString(QLatin1String(QByteArray::fromBase64(data))); + return Value::fromString(ctx, QString::fromUtf8(QByteArray::fromBase64(data))); } /*! @@ -1112,10 +914,12 @@ Within the \l {Prototyping with qmlscene}, this causes the launcher application to quit a C++ application when this method is called, connect the QQmlEngine::quit() signal to the QCoreApplication::quit() slot. */ -v8::Handle<v8::Value> quit(const v8::Arguments &args) +Value QtObject::method_quit(SimpleCallContext *ctx) { - QQmlEnginePrivate::get(V8ENGINE()->engine())->sendQuit(); - return v8::Undefined(); + QV8Engine *v8engine = ctx->engine->v8Engine; + + QQmlEnginePrivate::get(v8engine->engine())->sendQuit(); + return QV4::Value::undefinedValue(); } /*! @@ -1142,35 +946,35 @@ If this is the case, consider using \l{QtQml2::Qt::createComponent()}{Qt.createC See \l {Dynamic QML Object Creation from JavaScript} for more information on using this function. */ -v8::Handle<v8::Value> createQmlObject(const v8::Arguments &args) +Value QtObject::method_createQmlObject(SimpleCallContext *ctx) { - if (args.Length() < 2 || args.Length() > 3) - V8THROW_ERROR("Qt.createQmlObject(): Invalid arguments"); + if (ctx->argumentCount < 2 || ctx->argumentCount > 3) + V4THROW_ERROR("Qt.createQmlObject(): Invalid arguments"); struct Error { - static v8::Local<v8::Value> create(QV8Engine *engine, const QList<QQmlError> &errors) { + static Value create(QV8Engine *engine, const QList<QQmlError> &errors) { QString errorstr = QLatin1String("Qt.createQmlObject(): failed to create object: "); - v8::Local<v8::Array> qmlerrors = v8::Array::New(errors.count()); + QV4::ExecutionEngine *v4 = QV8Engine::getV4(engine); + QV4::ArrayObject *qmlerrors = v4->newArrayObject(); for (int ii = 0; ii < errors.count(); ++ii) { const QQmlError &error = errors.at(ii); errorstr += QLatin1String("\n ") + error.toString(); - v8::Local<v8::Object> qmlerror = v8::Object::New(); - qmlerror->Set(v8::String::New("lineNumber"), v8::Integer::New(error.line())); - qmlerror->Set(v8::String::New("columnNumber"), v8::Integer::New(error.column())); - qmlerror->Set(v8::String::New("fileName"), engine->toString(error.url().toString())); - qmlerror->Set(v8::String::New("message"), engine->toString(error.description())); - qmlerrors->Set(ii, qmlerror); + QV4::Object *qmlerror = v4->newObject(); + qmlerror->put(v4->newString("lineNumber"), QV4::Value::fromInt32(error.line())); + qmlerror->put(v4->newString("columnNumber"), QV4::Value::fromInt32(error.column())); + qmlerror->put(v4->newString("fileName"), engine->toString(error.url().toString())); + qmlerror->put(v4->newString("message"), engine->toString(error.description())); + qmlerrors->putIndexed(ii, QV4::Value::fromObject(qmlerror)); } - v8::Local<v8::Value> error = v8::Exception::Error(engine->toString(errorstr)); - v8::Local<v8::Object> errorObject = error->ToObject(); - errorObject->Set(v8::String::New("qmlErrors"), qmlerrors); - return error; + QV4::Object *errorObject = v4->newErrorObject(engine->toString(errorstr)); + errorObject->put(v4->newString("qmlErrors"), Value::fromObject(qmlerrors)); + return Value::fromObject(errorObject); } }; - QV8Engine *v8engine = V8ENGINE(); + QV8Engine *v8engine = ctx->engine->v8Engine; QQmlEngine *engine = v8engine->engine(); QQmlContextData *context = v8engine->callingContext(); @@ -1181,33 +985,35 @@ v8::Handle<v8::Value> createQmlObject(const v8::Arguments &args) effectiveContext = context->asQQmlContext(); Q_ASSERT(context && effectiveContext); - QString qml = v8engine->toString(args[0]->ToString()); + QString qml = ctx->arguments[0].toQString(); if (qml.isEmpty()) - return v8::Null(); + return QV4::Value::nullValue(); QUrl url; - if (args.Length() > 2) - url = QUrl(v8engine->toString(args[2]->ToString())); + if (ctx->argumentCount > 2) + url = QUrl(ctx->arguments[2].toQString()); else url = QUrl(QLatin1String("inline")); if (url.isValid() && url.isRelative()) url = context->resolvedUrl(url); - QObject *parentArg = v8engine->toQObject(args[1]); + QObject *parentArg = 0; + if (QV4::QObjectWrapper *qobjectWrapper = ctx->arguments[1].as<QV4::QObjectWrapper>()) + parentArg = qobjectWrapper->object(); if (!parentArg) - V8THROW_ERROR("Qt.createQmlObject(): Missing parent object"); + V4THROW_ERROR("Qt.createQmlObject(): Missing parent object"); QQmlComponent component(engine); component.setData(qml.toUtf8(), url); if (component.isError()) { - v8::ThrowException(Error::create(v8engine, component.errors())); - return v8::Undefined(); + ctx->throwError(Error::create(v8engine, component.errors())); + return QV4::Value::undefinedValue(); } if (!component.isReady()) - V8THROW_ERROR("Qt.createQmlObject(): Component is not ready"); + V4THROW_ERROR("Qt.createQmlObject(): Component is not ready"); QObject *obj = component.beginCreate(effectiveContext); if (obj) { @@ -1226,13 +1032,13 @@ v8::Handle<v8::Value> createQmlObject(const v8::Arguments &args) component.completeCreate(); if (component.isError()) { - v8::ThrowException(Error::create(v8engine, component.errors())); - return v8::Undefined(); + ctx->throwError(Error::create(v8engine, component.errors())); + return QV4::Value::undefinedValue(); } Q_ASSERT(obj); - return v8engine->newQObject(obj); + return QV4::QObjectWrapper::wrap(ctx->engine, obj); } /*! @@ -1266,14 +1072,14 @@ See \l {Dynamic QML Object Creation from JavaScript} for more information on usi To create a QML object from an arbitrary string of QML (instead of a file), use \l{QtQml2::Qt::createQmlObject()}{Qt.createQmlObject()}. */ -v8::Handle<v8::Value> createComponent(const v8::Arguments &args) +Value QtObject::method_createComponent(SimpleCallContext *ctx) { - const char *invalidArgs = "Qt.createComponent(): Invalid arguments"; - const char *invalidParent = "Qt.createComponent(): Invalid parent object"; - if (args.Length() < 1 || args.Length() > 3) - V8THROW_ERROR(invalidArgs); + const QString invalidArgs = QStringLiteral("Qt.createComponent(): Invalid arguments"); + const QString invalidParent = QStringLiteral("Qt.createComponent(): Invalid parent object"); + if (ctx->argumentCount < 1 || ctx->argumentCount > 3) + ctx->throwError(invalidArgs); - QV8Engine *v8engine = V8ENGINE(); + QV8Engine *v8engine = ctx->engine->v8Engine; QQmlEngine *engine = v8engine->engine(); QQmlContextData *context = v8engine->callingContext(); @@ -1282,39 +1088,40 @@ v8::Handle<v8::Value> createComponent(const v8::Arguments &args) effectiveContext = 0; Q_ASSERT(context); - QString arg = v8engine->toString(args[0]->ToString()); + QString arg = ctx->arguments[0].toQString(); if (arg.isEmpty()) - return v8::Null(); + return QV4::Value::nullValue(); QQmlComponent::CompilationMode compileMode = QQmlComponent::PreferSynchronous; QObject *parentArg = 0; int consumedCount = 1; - if (args.Length() > 1) { - const v8::Local<v8::Value> &lastArg = args[args.Length()-1]; + if (ctx->argumentCount > 1) { + Value lastArg = ctx->arguments[ctx->argumentCount-1]; // The second argument could be the mode enum - if (args[1]->IsInt32()) { - int mode = args[1]->Int32Value(); + if (ctx->arguments[1].isInteger()) { + int mode = ctx->arguments[1].integerValue(); if (mode != int(QQmlComponent::PreferSynchronous) && mode != int(QQmlComponent::Asynchronous)) - V8THROW_ERROR(invalidArgs); + ctx->throwError(invalidArgs); compileMode = QQmlComponent::CompilationMode(mode); consumedCount += 1; } else { // The second argument could be the parent only if there are exactly two args - if ((args.Length() != 2) || !(lastArg->IsObject() || lastArg->IsNull())) - V8THROW_ERROR(invalidArgs); + if ((ctx->argumentCount != 2) || !(lastArg.isObject() || lastArg.isNull())) + ctx->throwError(invalidArgs); } - if (consumedCount < args.Length()) { - if (lastArg->IsObject()) { - parentArg = v8engine->toQObject(lastArg); + if (consumedCount < ctx->argumentCount) { + if (lastArg.isObject()) { + if (QV4::QObjectWrapper *qobjectWrapper = lastArg.as<QV4::QObjectWrapper>()) + parentArg = qobjectWrapper->object(); if (!parentArg) - V8THROW_ERROR(invalidParent); - } else if (lastArg->IsNull()) { + ctx->throwError(invalidParent); + } else if (lastArg.isNull()) { parentArg = 0; } else { - V8THROW_ERROR(invalidParent); + ctx->throwError(invalidParent); } } } @@ -1325,9 +1132,471 @@ v8::Handle<v8::Value> createComponent(const v8::Arguments &args) QQmlData::get(c, true)->explicitIndestructibleSet = false; QQmlData::get(c)->indestructible = false; - return v8engine->newQObject(c); + return QV4::QObjectWrapper::wrap(ctx->engine, c); +} + +/*! + \qmlmethod Qt::locale(name) + + Returns a JS object representing the locale with the specified + name, which has the format "language[_territory][.codeset][@modifier]" + or "C", where: + + \list + \li language is a lowercase, two-letter, ISO 639 language code, + \li territory is an uppercase, two-letter, ISO 3166 country code, + \li and codeset and modifier are ignored. + \endlist + + If the string violates the locale format, or language is not a + valid ISO 369 code, the "C" locale is used instead. If country + is not present, or is not a valid ISO 3166 code, the most + appropriate country is chosen for the specified language. + + \sa QtQuick2::Locale +*/ +Value QtObject::method_locale(SimpleCallContext *ctx) +{ + QString code; + if (ctx->argumentCount > 1) + V4THROW_ERROR("locale() requires 0 or 1 argument"); + if (ctx->argumentCount == 1 && !ctx->arguments[0].isString()) + V4THROW_TYPE("locale(): argument (locale code) must be a string"); + + QV8Engine *v8engine = ctx->engine->v8Engine; + if (ctx->argumentCount == 1) + code = ctx->arguments[0].toQString(); + + return QQmlLocale::locale(v8engine, code); +} + +namespace { + +struct BindingFunction : public QV4::FunctionObject +{ + Q_MANAGED + BindingFunction(FunctionObject *originalFunction) + : QV4::FunctionObject(originalFunction->scope, originalFunction->name) + , originalFunction(originalFunction) + { + vtbl = &static_vtbl; + bindingKeyFlag = true; + } + + static Value call(Managed *that, const Value &thisObject, Value *argv, int argc) + { + BindingFunction *This = static_cast<BindingFunction*>(that); + return This->originalFunction->call(thisObject, argv, argc); + } + + static void markObjects(Managed *that) + { + BindingFunction *This = static_cast<BindingFunction*>(that); + This->originalFunction->mark(); + QV4::FunctionObject::markObjects(that); + } + + QV4::FunctionObject *originalFunction; +}; + +DEFINE_MANAGED_VTABLE(BindingFunction); + } +/*! + \qmlmethod Qt::binding(function) + + Returns a JS object representing a binding expression which may be + assigned to any property in imperative code to cause a binding + assignment. + + There are two main use-cases for the function: firstly, in imperative + JavaScript code to cause a binding assignment: + + \snippet qml/qtBinding.1.qml 0 + + and secondly, when defining initial property values of dynamically + constructed objects (via Component.createObject() or + Loader.setSource()) as being bound to the result of an expression. + + For example, assuming the existence of a DynamicText component: + \snippet qml/DynamicText.qml 0 + + the output from: + \snippet qml/qtBinding.2.qml 0 + + and from: + \snippet qml/qtBinding.3.qml 0 + + should both be: + \code + Root text extra text + Modified root text extra text + Dynamic text extra text + Modified dynamic text extra text + \endcode + + This function cannot be used in property binding declarations + (see the documentation on \l{qml-javascript-assignment}{binding + declarations and binding assignments}) except when the result is + stored in an array bound to a var property. + + \snippet qml/qtBinding.4.qml 0 + + \note In \l {Qt Quick 1}, all function assignment was treated as + binding assignment, so the Qt.binding() function is new in + \l {Qt Quick}{Qt Quick 2}. + + \since QtQuick 2.0 +*/ +Value QtObject::method_binding(SimpleCallContext *ctx) +{ + if (ctx->argumentCount != 1) + V4THROW_ERROR("binding() requires 1 argument"); + QV4::FunctionObject *f = ctx->arguments[0].asFunctionObject(); + if (!f) + V4THROW_TYPE("binding(): argument (binding expression) must be a function"); + + return QV4::Value::fromObject(new (ctx->engine->memoryManager) BindingFunction(f)); +} + + +Value QtObject::method_get_platform(SimpleCallContext *ctx) +{ + // ### inefficient. Should be just a value based getter + Object *o = ctx->thisObject.asObject(); + if (!o) + ctx->throwTypeError(); + QtObject *qt = o->as<QtObject>(); + if (!qt) + ctx->throwTypeError(); + + if (!qt->m_platform) + // Only allocate a platform object once + qt->m_platform = new QQmlPlatform(ctx->engine->v8Engine->publicEngine()); + + return QV4::QObjectWrapper::wrap(ctx->engine, qt->m_platform); +} + +Value QtObject::method_get_application(SimpleCallContext *ctx) +{ + // ### inefficient. Should be just a value based getter + Object *o = ctx->thisObject.asObject(); + if (!o) + ctx->throwTypeError(); + QtObject *qt = o->as<QtObject>(); + if (!qt) + ctx->throwTypeError(); + + if (!qt->m_application) + // Only allocate an application object once + qt->m_application = QQml_guiProvider()->application(ctx->engine->v8Engine->publicEngine()); + + return QV4::QObjectWrapper::wrap(ctx->engine, qt->m_application); +} + +#ifndef QT_NO_IM +Value QtObject::method_get_inputMethod(SimpleCallContext *ctx) +{ + QObject *o = QQml_guiProvider()->inputMethod(); + QQmlEngine::setObjectOwnership(o, QQmlEngine::CppOwnership); + return QV4::QObjectWrapper::wrap(ctx->engine, o); +} +#endif + + +QV4::ConsoleObject::ConsoleObject(ExecutionEngine *v4) + : Object(v4) +{ + defineDefaultProperty(v4, QStringLiteral("debug"), method_log); + defineDefaultProperty(v4, QStringLiteral("log"), method_log); + defineDefaultProperty(v4, QStringLiteral("info"), method_log); + defineDefaultProperty(v4, QStringLiteral("warn"), method_warn); + defineDefaultProperty(v4, QStringLiteral("error"), method_error); + defineDefaultProperty(v4, QStringLiteral("assert"), method_assert); + + defineDefaultProperty(v4, QStringLiteral("count"), method_count); + defineDefaultProperty(v4, QStringLiteral("profile"), method_profile); + defineDefaultProperty(v4, QStringLiteral("profileEnd"), method_profileEnd); + defineDefaultProperty(v4, QStringLiteral("time"), method_time); + defineDefaultProperty(v4, QStringLiteral("timeEnd"), method_timeEnd); + defineDefaultProperty(v4, QStringLiteral("trace"), method_trace); + defineDefaultProperty(v4, QStringLiteral("exception"), method_exception); +} + + +enum ConsoleLogTypes { + Log, + Warn, + Error +}; + +static QString jsStack(QV4::ExecutionEngine *engine) { + QString stack; + + QVector<QV4::ExecutionEngine::StackFrame> stackTrace = engine->stackTrace(10); + + for (int i = 0; i < stackTrace.count(); i++) { + const QV4::ExecutionEngine::StackFrame &frame = stackTrace.at(i); + + QString stackFrame; + if (frame.column >= 0) + stackFrame = QString::fromLatin1("%1 (%2:%3:%4)").arg(frame.function, + frame.source, + QString::number(frame.line), + QString::number(frame.column)); + else + stackFrame = QString::fromLatin1("%1 (%2:%3)").arg(frame.function, + frame.source, + QString::number(frame.line)); + + if (i) + stack += QChar('\n'); + stack += stackFrame; + } + return stack; +} + +static QV4::Value writeToConsole(ConsoleLogTypes logType, SimpleCallContext *ctx, + bool printStack = false) +{ + QString result; + QV4::ExecutionEngine *v4 = ctx->engine; + + for (int i = 0; i < ctx->argumentCount; ++i) { + if (i != 0) + result.append(QLatin1Char(' ')); + + QV4::Value value = ctx->arguments[i]; + if (value.asArrayObject()) + result.append(QStringLiteral("[") + value.toQString() + QStringLiteral("]")); + else + result.append(value.toQString()); + } + + if (printStack) { + result.append(QLatin1String("\n")); + result.append(jsStack(v4)); + } + + QV4::ExecutionEngine::StackFrame frame = v4->currentStackFrame(); + QMessageLogger logger(frame.source.toUtf8().constData(), frame.line, frame.function.toUtf8().constData()); + switch (logType) { + case Log: + logger.debug("%s", qPrintable(result)); + break; + case Warn: + logger.warning("%s", qPrintable(result)); + break; + case Error: + logger.critical("%s", qPrintable(result)); + break; + default: + break; + } + + return QV4::Value::undefinedValue(); +} + +QV4::Value ConsoleObject::method_error(SimpleCallContext *ctx) +{ + return writeToConsole(Error, ctx); +} + +QV4::Value ConsoleObject::method_log(SimpleCallContext *ctx) +{ + //console.log + //console.debug + //console.info + //print + return writeToConsole(Log, ctx); +} + +QV4::Value ConsoleObject::method_profile(SimpleCallContext *ctx) +{ + //DeclarativeDebugTrace cannot handle nested profiling + //although v8 can handle several profiling at once, + //we do not allow that. Hence, we pass an empty(default) title + QString title; + QV4::ExecutionEngine *v4 = ctx->engine; + + QV4::ExecutionEngine::StackFrame frame = v4->currentStackFrame(); + QMessageLogger logger(frame.source.toUtf8().constData(), frame.line, frame.function.toUtf8().constData()); + if (QQmlProfilerService::startProfiling()) { + QV8ProfilerService::instance()->startProfiling(title); + + logger.debug("Profiling started."); + } else { + logger.warning("Profiling is already in progress. First, end current profiling session."); + } + + return QV4::Value::undefinedValue(); +} + +QV4::Value ConsoleObject::method_profileEnd(SimpleCallContext *ctx) +{ + //DeclarativeDebugTrace cannot handle nested profiling + //although v8 can handle several profiling at once, + //we do not allow that. Hence, we pass an empty(default) title + QString title; + + QV4::ExecutionEngine *v4 = ctx->engine; + + QV4::ExecutionEngine::StackFrame frame = v4->currentStackFrame(); + QMessageLogger logger(frame.source.toUtf8().constData(), frame.line, frame.function.toUtf8().constData()); + + if (QQmlProfilerService::stopProfiling()) { + QV8ProfilerService *profiler = QV8ProfilerService::instance(); + profiler->stopProfiling(title); + QQmlProfilerService::sendProfilingData(); + profiler->sendProfilingData(); + + logger.debug("Profiling ended."); + } else { + logger.warning("Profiling was not started."); + } + + return QV4::Value::undefinedValue(); +} + +QV4::Value ConsoleObject::method_time(SimpleCallContext *ctx) +{ + if (ctx->argumentCount != 1) + V4THROW_ERROR("console.time(): Invalid arguments"); + + QV8Engine *v8engine = ctx->engine->v8Engine; + + QString name = ctx->arguments[0].toQString(); + v8engine->startTimer(name); + return QV4::Value::undefinedValue(); +} + +QV4::Value ConsoleObject::method_timeEnd(SimpleCallContext *ctx) +{ + if (ctx->argumentCount != 1) + V4THROW_ERROR("console.time(): Invalid arguments"); + + QV8Engine *v8engine = ctx->engine->v8Engine; + + QString name = ctx->arguments[0].toQString(); + bool wasRunning; + qint64 elapsed = v8engine->stopTimer(name, &wasRunning); + if (wasRunning) { + qDebug("%s: %llims", qPrintable(name), elapsed); + } + return QV4::Value::undefinedValue(); +} + +QV4::Value ConsoleObject::method_count(SimpleCallContext *ctx) +{ + // first argument: name to print. Ignore any additional arguments + QString name; + if (ctx->argumentCount > 0) + name = ctx->arguments[0].toQString(); + + QV4::ExecutionEngine *v4 = ctx->engine; + QV8Engine *v8engine = ctx->engine->v8Engine; + + QV4::ExecutionEngine::StackFrame frame = v4->currentStackFrame(); + + QString scriptName = frame.source; + + int value = v8engine->consoleCountHelper(scriptName, frame.line, frame.column); + QString message = name + QLatin1String(": ") + QString::number(value); + + QMessageLogger(qPrintable(scriptName), frame.line, + qPrintable(frame.function)).debug("%s", qPrintable(message)); + + return QV4::Value::undefinedValue(); +} + +QV4::Value ConsoleObject::method_trace(SimpleCallContext *ctx) +{ + if (ctx->argumentCount != 0) + V4THROW_ERROR("console.trace(): Invalid arguments"); + + QV4::ExecutionEngine *v4 = ctx->engine; + + QString stack = jsStack(v4); + + QV4::ExecutionEngine::StackFrame frame = v4->currentStackFrame(); + QMessageLogger logger(frame.source.toUtf8().constData(), frame.line, frame.function.toUtf8().constData()); + + logger.debug("%s", qPrintable(stack)); + return QV4::Value::undefinedValue(); +} + +QV4::Value ConsoleObject::method_warn(SimpleCallContext *ctx) +{ + return writeToConsole(Warn, ctx); +} + +QV4::Value ConsoleObject::method_assert(SimpleCallContext *ctx) +{ + if (ctx->argumentCount == 0) + V4THROW_ERROR("console.assert(): Missing argument"); + + QV4::ExecutionEngine *v4 = ctx->engine; + + if (!ctx->arguments[0].toBoolean()) { + QString message; + for (int i = 1; i < ctx->argumentCount; ++i) { + if (i != 1) + message.append(QLatin1Char(' ')); + + message.append(ctx->arguments[i].toQString()); + } + + QString stack = jsStack(v4); + + QV4::ExecutionEngine::StackFrame frame = v4->currentStackFrame(); + QMessageLogger logger(frame.source.toUtf8().constData(), frame.line, frame.function.toUtf8().constData()); + logger.critical("%s\n%s", qPrintable(message), qPrintable(stack)); + + } + return QV4::Value::undefinedValue(); +} + +QV4::Value ConsoleObject::method_exception(SimpleCallContext *ctx) +{ + if (ctx->argumentCount == 0) + V4THROW_ERROR("console.exception(): Missing argument"); + + writeToConsole(Error, ctx, true); + + return QV4::Value::undefinedValue(); +} + + + +void QV4::GlobalExtensions::init(QQmlEngine *qmlEngine, Object *globalObject) +{ + QV4::ExecutionEngine *v4 = globalObject->engine(); + +#ifndef QT_NO_TRANSLATION + globalObject->defineDefaultProperty(v4, QStringLiteral("qsTranslate"), method_qsTranslate); + globalObject->defineDefaultProperty(v4, QStringLiteral("QT_TRANSLATE_NOOP"), method_qsTranslateNoOp); + globalObject->defineDefaultProperty(v4, QStringLiteral("qsTr"), method_qsTr); + globalObject->defineDefaultProperty(v4, QStringLiteral("QT_TR_NOOP"), method_qsTrNoOp); + globalObject->defineDefaultProperty(v4, QStringLiteral("qsTrId"), method_qsTrId); + globalObject->defineDefaultProperty(v4, QStringLiteral("QT_TRID_NOOP"), method_qsTrIdNoOp); +#endif + + globalObject->defineDefaultProperty(v4, QStringLiteral("print"), ConsoleObject::method_log); + globalObject->defineDefaultProperty(v4, QStringLiteral("gc"), method_gc); + + Value console = QV4::Value::fromObject(new (v4->memoryManager) QV4::ConsoleObject(v4)); + globalObject->defineDefaultProperty(v4, QStringLiteral("console"), console); + + Value qt = QV4::Value::fromObject(new (v4->memoryManager) QV4::QtObject(v4, qmlEngine)); + globalObject->defineDefaultProperty(v4, QStringLiteral("Qt"), qt); + + // string prototype extension + QV4::Object *stringProto = v4->stringPrototype; + stringProto->defineDefaultProperty(v4, QStringLiteral("arg"), string_arg); +} + + #ifndef QT_NO_TRANSLATION /*! \qmlmethod string Qt::qsTranslate(string context, string sourceText, string disambiguation, int n) @@ -1346,39 +1615,38 @@ v8::Handle<v8::Value> createComponent(const v8::Arguments &args) \sa {Internationalization and Localization with Qt Quick} */ -v8::Handle<v8::Value> qsTranslate(const v8::Arguments &args) +Value GlobalExtensions::method_qsTranslate(SimpleCallContext *ctx) { - if (args.Length() < 2) - V8THROW_ERROR("qsTranslate() requires at least two arguments"); - if (!args[0]->IsString()) - V8THROW_ERROR("qsTranslate(): first argument (context) must be a string"); - if (!args[1]->IsString()) - V8THROW_ERROR("qsTranslate(): second argument (sourceText) must be a string"); - if ((args.Length() > 2) && !args[2]->IsString()) - V8THROW_ERROR("qsTranslate(): third argument (disambiguation) must be a string"); - - QV8Engine *v8engine = V8ENGINE(); - QString context = v8engine->toString(args[0]); - QString text = v8engine->toString(args[1]); + if (ctx->argumentCount < 2) + V4THROW_ERROR("qsTranslate() requires at least two arguments"); + if (!ctx->arguments[0].isString()) + V4THROW_ERROR("qsTranslate(): first argument (context) must be a string"); + if (!ctx->arguments[1].isString()) + V4THROW_ERROR("qsTranslate(): second argument (sourceText) must be a string"); + if ((ctx->argumentCount > 2) && !ctx->arguments[2].isString()) + V4THROW_ERROR("qsTranslate(): third argument (disambiguation) must be a string"); + + QString context = ctx->arguments[0].toQString(); + QString text = ctx->arguments[1].toQString(); QString comment; - if (args.Length() > 2) comment = v8engine->toString(args[2]); + if (ctx->argumentCount > 2) comment = ctx->arguments[2].toQString(); int i = 3; - if (args.Length() > i && args[i]->IsString()) { + if (ctx->argumentCount > i && ctx->arguments[i].isString()) { qWarning("qsTranslate(): specifying the encoding as fourth argument is deprecated"); ++i; } int n = -1; - if (args.Length() > i) - n = args[i]->Int32Value(); + if (ctx->argumentCount > i) + n = ctx->arguments[i].toInt32(); QString result = QCoreApplication::translate(context.toUtf8().constData(), text.toUtf8().constData(), comment.toUtf8().constData(), n); - return v8engine->toString(result); + return Value::fromString(ctx, result); } /*! @@ -1403,11 +1671,11 @@ v8::Handle<v8::Value> qsTranslate(const v8::Arguments &args) \sa {Internationalization and Localization with Qt Quick} */ -v8::Handle<v8::Value> qsTranslateNoOp(const v8::Arguments &args) +Value GlobalExtensions::method_qsTranslateNoOp(SimpleCallContext *ctx) { - if (args.Length() < 2) - return v8::Undefined(); - return args[1]; + if (ctx->argumentCount < 2) + return QV4::Value::undefinedValue(); + return ctx->arguments[1]; } /*! @@ -1427,36 +1695,36 @@ v8::Handle<v8::Value> qsTranslateNoOp(const v8::Arguments &args) \sa {Internationalization and Localization with Qt Quick} */ -v8::Handle<v8::Value> qsTr(const v8::Arguments &args) +Value GlobalExtensions::method_qsTr(SimpleCallContext *ctx) { - if (args.Length() < 1) - V8THROW_ERROR("qsTr() requires at least one argument"); - if (!args[0]->IsString()) - V8THROW_ERROR("qsTr(): first argument (sourceText) must be a string"); - if ((args.Length() > 1) && !args[1]->IsString()) - V8THROW_ERROR("qsTr(): second argument (disambiguation) must be a string"); - if ((args.Length() > 2) && !args[2]->IsNumber()) - V8THROW_ERROR("qsTr(): third argument (n) must be a number"); - - QV8Engine *v8engine = V8ENGINE(); + if (ctx->argumentCount < 1) + V4THROW_ERROR("qsTr() requires at least one argument"); + if (!ctx->arguments[0].isString()) + V4THROW_ERROR("qsTr(): first argument (sourceText) must be a string"); + if ((ctx->argumentCount > 1) && !ctx->arguments[1].isString()) + V4THROW_ERROR("qsTr(): second argument (disambiguation) must be a string"); + if ((ctx->argumentCount > 2) && !ctx->arguments[2].isNumber()) + V4THROW_ERROR("qsTr(): third argument (n) must be a number"); + + QV8Engine *v8engine = ctx->engine->v8Engine; QQmlContextData *ctxt = v8engine->callingContext(); QString path = ctxt->url.toString(); int lastSlash = path.lastIndexOf(QLatin1Char('/')); QString context = (lastSlash > -1) ? path.mid(lastSlash + 1, path.length()-lastSlash-5) : QString(); - QString text = v8engine->toString(args[0]); + QString text = ctx->arguments[0].toQString(); QString comment; - if (args.Length() > 1) - comment = v8engine->toString(args[1]); + if (ctx->argumentCount > 1) + comment = ctx->arguments[1].toQString(); int n = -1; - if (args.Length() > 2) - n = args[2]->Int32Value(); + if (ctx->argumentCount > 2) + n = ctx->arguments[2].toInt32(); QString result = QCoreApplication::translate(context.toUtf8().constData(), text.toUtf8().constData(), comment.toUtf8().constData(), n); - return v8engine->toString(result); + return Value::fromString(ctx, result); } /*! @@ -1481,11 +1749,11 @@ v8::Handle<v8::Value> qsTr(const v8::Arguments &args) \sa {Internationalization and Localization with Qt Quick} */ -v8::Handle<v8::Value> qsTrNoOp(const v8::Arguments &args) +Value GlobalExtensions::method_qsTrNoOp(SimpleCallContext *ctx) { - if (args.Length() < 1) - return v8::Undefined(); - return args[0]; + if (ctx->argumentCount < 1) + return QV4::Value::undefinedValue(); + return ctx->arguments[0]; } /*! @@ -1518,21 +1786,20 @@ v8::Handle<v8::Value> qsTrNoOp(const v8::Arguments &args) \sa QT_TRID_NOOP, {Internationalization and Localization with Qt Quick} */ -v8::Handle<v8::Value> qsTrId(const v8::Arguments &args) +Value GlobalExtensions::method_qsTrId(SimpleCallContext *ctx) { - if (args.Length() < 1) - V8THROW_ERROR("qsTrId() requires at least one argument"); - if (!args[0]->IsString()) - V8THROW_TYPE("qsTrId(): first argument (id) must be a string"); - if (args.Length() > 1 && !args[1]->IsNumber()) - V8THROW_TYPE("qsTrId(): second argument (n) must be a number"); + if (ctx->argumentCount < 1) + V4THROW_ERROR("qsTrId() requires at least one argument"); + if (!ctx->arguments[0].isString()) + V4THROW_TYPE("qsTrId(): first argument (id) must be a string"); + if (ctx->argumentCount > 1 && !ctx->arguments[1].isNumber()) + V4THROW_TYPE("qsTrId(): second argument (n) must be a number"); int n = -1; - if (args.Length() > 1) - n = args[1]->Int32Value(); + if (ctx->argumentCount > 1) + n = ctx->arguments[1].toInt32(); - QV8Engine *v8engine = V8ENGINE(); - return v8engine->toString(qtTrId(v8engine->toString(args[0]).toUtf8().constData(), n)); + return Value::fromString(ctx, qtTrId(ctx->arguments[0].toQString().toUtf8().constData(), n)); } /*! @@ -1551,108 +1818,41 @@ v8::Handle<v8::Value> qsTrId(const v8::Arguments &args) \sa qsTrId(), {Internationalization and Localization with Qt Quick} */ -v8::Handle<v8::Value> qsTrIdNoOp(const v8::Arguments &args) +Value GlobalExtensions::method_qsTrIdNoOp(SimpleCallContext *ctx) { - if (args.Length() < 1) - return v8::Undefined(); - return args[0]; + if (ctx->argumentCount < 1) + return QV4::Value::undefinedValue(); + return ctx->arguments[0]; } #endif // QT_NO_TRANSLATION -/*! - \qmlmethod Qt::locale(name) - Returns a JS object representing the locale with the specified - name, which has the format "language[_territory][.codeset][@modifier]" - or "C", where: - - \list - \li language is a lowercase, two-letter, ISO 639 language code, - \li territory is an uppercase, two-letter, ISO 3166 country code, - \li and codeset and modifier are ignored. - \endlist - - If the string violates the locale format, or language is not a - valid ISO 369 code, the "C" locale is used instead. If country - is not present, or is not a valid ISO 3166 code, the most - appropriate country is chosen for the specified language. - - \sa QtQuick2::Locale -*/ -v8::Handle<v8::Value> locale(const v8::Arguments &args) +QV4::Value GlobalExtensions::method_gc(SimpleCallContext *ctx) { - QString code; - if (args.Length() > 1) - V8THROW_ERROR("locale() requires 0 or 1 argument"); - if (args.Length() == 1 && !args[0]->IsString()) - V8THROW_TYPE("locale(): argument (locale code) must be a string"); - - QV8Engine *v8engine = V8ENGINE(); - if (args.Length() == 1) - code = v8engine->toString(args[0]); + ctx->engine->memoryManager->runGC(); - return QQmlLocale::locale(v8engine, code); + return QV4::Value::undefinedValue(); } -/*! - \qmlmethod Qt::binding(function) - - Returns a JS object representing a binding expression which may be - assigned to any property in imperative code to cause a binding - assignment. - There are two main use-cases for the function: firstly, in imperative - JavaScript code to cause a binding assignment: - \snippet qml/qtBinding.1.qml 0 - - and secondly, when defining initial property values of dynamically - constructed objects (via Component.createObject() or - Loader.setSource()) as being bound to the result of an expression. - - For example, assuming the existence of a DynamicText component: - \snippet qml/DynamicText.qml 0 - - the output from: - \snippet qml/qtBinding.2.qml 0 - - and from: - \snippet qml/qtBinding.3.qml 0 - - should both be: - \code - Root text extra text - Modified root text extra text - Dynamic text extra text - Modified dynamic text extra text - \endcode - - This function cannot be used in property binding declarations - (see the documentation on \l{qml-javascript-assignment}{binding - declarations and binding assignments}) except when the result is - stored in an array bound to a var property. - - \snippet qml/qtBinding.4.qml 0 - - \note In \l {Qt Quick 1}, all function assignment was treated as - binding assignment, so the Qt.binding() function is new in - \l {Qt Quick}{Qt Quick 2}. - - \since QtQuick 2.0 -*/ -v8::Handle<v8::Value> binding(const v8::Arguments &args) +Value GlobalExtensions::string_arg(SimpleCallContext *ctx) { - QString code; - if (args.Length() != 1) - V8THROW_ERROR("binding() requires 1 argument"); - if (!args[0]->IsFunction()) - V8THROW_TYPE("binding(): argument (binding expression) must be a function"); - - v8::Handle<v8::Object> rv = args[0]->ToObject()->Clone(); - rv->SetHiddenValue(V8ENGINE()->bindingFlagKey(), v8::Boolean::New(true)); - return rv; + QString value = ctx->thisObject.toQString(); + if (ctx->argumentCount != 1) + V4THROW_ERROR("String.arg(): Invalid arguments"); + + QV4::Value arg = ctx->arguments[0]; + if (arg.isInteger()) + return Value::fromString(ctx, value.arg(arg.integerValue())); + else if (arg.isDouble()) + return Value::fromString(ctx, value.arg(arg.doubleValue())); + else if (arg.isBoolean()) + return Value::fromString(ctx, value.arg(arg.booleanValue())); + + return Value::fromString(ctx, value.arg(arg.toQString())); } -} // namespace QQmlBuiltinFunctions QT_END_NAMESPACE + diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions_p.h b/src/qml/qml/v8/qqmlbuiltinfunctions_p.h index f73802b136..c0effacbb4 100644 --- a/src/qml/qml/v8/qqmlbuiltinfunctions_p.h +++ b/src/qml/qml/v8/qqmlbuiltinfunctions_p.h @@ -54,63 +54,98 @@ // #include <QtCore/qglobal.h> -#include <private/qv8_p.h> +#include <private/qv4object_p.h> + +class QQmlEngine; +class QV8Engine; QT_BEGIN_NAMESPACE -namespace QQmlBuiltinFunctions +namespace QV4 { + +struct QtObject : Object +{ + Q_MANAGED + QtObject(ExecutionEngine *v4, QQmlEngine *qmlEngine); + + static Value method_isQtObject(SimpleCallContext *ctx); + static Value method_rgba(SimpleCallContext *ctx); + static Value method_hsla(SimpleCallContext *ctx); + static Value method_colorEqual(SimpleCallContext *ctx); + static Value method_font(SimpleCallContext *ctx); + static Value method_rect(SimpleCallContext *ctx); + static Value method_point(SimpleCallContext *ctx); + static Value method_size(SimpleCallContext *ctx); + static Value method_vector2d(SimpleCallContext *ctx); + static Value method_vector3d(SimpleCallContext *ctx); + static Value method_vector4d(SimpleCallContext *ctx); + static Value method_quaternion(SimpleCallContext *ctx); + static Value method_matrix4x4(SimpleCallContext *ctx); + static Value method_lighter(SimpleCallContext *ctx); + static Value method_darker(SimpleCallContext *ctx); + static Value method_tint(SimpleCallContext *ctx); + static Value method_formatDate(SimpleCallContext *ctx); + static Value method_formatTime(SimpleCallContext *ctx); + static Value method_formatDateTime(SimpleCallContext *ctx); + static Value method_openUrlExternally(SimpleCallContext *ctx); + static Value method_fontFamilies(SimpleCallContext *ctx); + static Value method_md5(SimpleCallContext *ctx); + static Value method_btoa(SimpleCallContext *ctx); + static Value method_atob(SimpleCallContext *ctx); + static Value method_quit(SimpleCallContext *ctx); + static Value method_resolvedUrl(SimpleCallContext *ctx); + static Value method_createQmlObject(SimpleCallContext *ctx); + static Value method_createComponent(SimpleCallContext *ctx); + static Value method_locale(SimpleCallContext *ctx); + static Value method_binding(SimpleCallContext *ctx); + + static Value method_get_platform(SimpleCallContext *ctx); + static Value method_get_application(SimpleCallContext *ctx); +#ifndef QT_NO_IM + static Value method_get_inputMethod(SimpleCallContext *ctx); +#endif + + QObject *m_platform; + QObject *m_application; +}; + +struct ConsoleObject : Object { -v8::Handle<v8::Value> gc(const v8::Arguments &args); -v8::Handle<v8::Value> consoleError(const v8::Arguments &args); -v8::Handle<v8::Value> consoleLog(const v8::Arguments &args); -v8::Handle<v8::Value> consoleProfile(const v8::Arguments &args); -v8::Handle<v8::Value> consoleProfileEnd(const v8::Arguments &args); -v8::Handle<v8::Value> consoleTime(const v8::Arguments &args); -v8::Handle<v8::Value> consoleTimeEnd(const v8::Arguments &args); -v8::Handle<v8::Value> consoleCount(const v8::Arguments &args); -v8::Handle<v8::Value> consoleTrace(const v8::Arguments &args); -v8::Handle<v8::Value> consoleWarn(const v8::Arguments &args); -v8::Handle<v8::Value> consoleAssert(const v8::Arguments &args); -v8::Handle<v8::Value> consoleException(const v8::Arguments &args); -v8::Handle<v8::Value> isQtObject(const v8::Arguments &args); -v8::Handle<v8::Value> rgba(const v8::Arguments &args); -v8::Handle<v8::Value> hsla(const v8::Arguments &args); -v8::Handle<v8::Value> colorEqual(const v8::Arguments &args); -v8::Handle<v8::Value> font(const v8::Arguments &args); -v8::Handle<v8::Value> rect(const v8::Arguments &args); -v8::Handle<v8::Value> point(const v8::Arguments &args); -v8::Handle<v8::Value> size(const v8::Arguments &args); -v8::Handle<v8::Value> vector2d(const v8::Arguments &args); -v8::Handle<v8::Value> vector3d(const v8::Arguments &args); -v8::Handle<v8::Value> vector4d(const v8::Arguments &args); -v8::Handle<v8::Value> quaternion(const v8::Arguments &args); -v8::Handle<v8::Value> matrix4x4(const v8::Arguments &args); -v8::Handle<v8::Value> lighter(const v8::Arguments &args); -v8::Handle<v8::Value> darker(const v8::Arguments &args); -v8::Handle<v8::Value> tint(const v8::Arguments &args); -v8::Handle<v8::Value> formatDate(const v8::Arguments &args); -v8::Handle<v8::Value> formatTime(const v8::Arguments &args); -v8::Handle<v8::Value> formatDateTime(const v8::Arguments &args); -v8::Handle<v8::Value> openUrlExternally(const v8::Arguments &args); -v8::Handle<v8::Value> fontFamilies(const v8::Arguments &args); -v8::Handle<v8::Value> md5(const v8::Arguments &args); -v8::Handle<v8::Value> btoa(const v8::Arguments &args); -v8::Handle<v8::Value> atob(const v8::Arguments &args); -v8::Handle<v8::Value> quit(const v8::Arguments &args); -v8::Handle<v8::Value> resolvedUrl(const v8::Arguments &args); -v8::Handle<v8::Value> createQmlObject(const v8::Arguments &args); -v8::Handle<v8::Value> createComponent(const v8::Arguments &args); + ConsoleObject(ExecutionEngine *v4); + + static Value method_error(SimpleCallContext *ctx); + static Value method_log(SimpleCallContext *ctx); + static Value method_profile(SimpleCallContext *ctx); + static Value method_profileEnd(SimpleCallContext *ctx); + static Value method_time(SimpleCallContext *ctx); + static Value method_timeEnd(SimpleCallContext *ctx); + static Value method_count(SimpleCallContext *ctx); + static Value method_trace(SimpleCallContext *ctx); + static Value method_warn(SimpleCallContext *ctx); + static Value method_assert(SimpleCallContext *ctx); + static Value method_exception(SimpleCallContext *ctx); + +}; + +struct GlobalExtensions { + static void init(QQmlEngine *qmlEngine, Object *globalObject); + #ifndef QT_NO_TRANSLATION -v8::Handle<v8::Value> qsTranslate(const v8::Arguments &args); -v8::Handle<v8::Value> qsTranslateNoOp(const v8::Arguments &args); -v8::Handle<v8::Value> qsTr(const v8::Arguments &args); -v8::Handle<v8::Value> qsTrNoOp(const v8::Arguments &args); -v8::Handle<v8::Value> qsTrId(const v8::Arguments &args); -v8::Handle<v8::Value> qsTrIdNoOp(const v8::Arguments &args); + static Value method_qsTranslate(SimpleCallContext *ctx); + static Value method_qsTranslateNoOp(SimpleCallContext *ctx); + static Value method_qsTr(SimpleCallContext *ctx); + static Value method_qsTrNoOp(SimpleCallContext *ctx); + static Value method_qsTrId(SimpleCallContext *ctx); + static Value method_qsTrIdNoOp(SimpleCallContext *ctx); #endif -v8::Handle<v8::Value> stringArg(const v8::Arguments &args); -v8::Handle<v8::Value> locale(const v8::Arguments &args); -v8::Handle<v8::Value> binding(const v8::Arguments &args); + static Value method_gc(SimpleCallContext *ctx); + + // on String:prototype + static Value string_arg(SimpleCallContext *ctx); + +}; + + } QT_END_NAMESPACE diff --git a/src/qml/qml/v8/qscript_impl_p.h b/src/qml/qml/v8/qscript_impl_p.h deleted file mode 100644 index 41791189a7..0000000000 --- a/src/qml/qml/v8/qscript_impl_p.h +++ /dev/null @@ -1,61 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#ifndef QSCRIPT_IMPL_P_H -#define QSCRIPT_IMPL_P_H - -#include "qv8engine_impl_p.h" -#include "qjsvalue_impl_p.h" -#include "qjsvalueiterator_impl_p.h" -#include "qjsconverter_impl_p.h" - -#endif //QSCRIPT_IMPL_P_H diff --git a/src/qml/qml/v8/qscriptisolate_p.h b/src/qml/qml/v8/qscriptisolate_p.h deleted file mode 100644 index da35069e33..0000000000 --- a/src/qml/qml/v8/qscriptisolate_p.h +++ /dev/null @@ -1,89 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef APIPREAMBLE_P_H -#define APIPREAMBLE_P_H - -#include <private/qv8_p.h> -#include "qv8engine_p.h" - -QT_BEGIN_NAMESPACE - -/** - \internal - Class used to switch to the right isolate. It does the same thing as v8::Isolate::Scope but - it checks for a null engine. - \attention We decided to put context switching "up" which means that it should be as high - as possible on call stack. And it should be switched at most once per public API function call. -*/ -class QScriptIsolate { -public: - // OperationMode was introduced to reduce number of checking for a null engine pointer. If we - // know that given pointer is not null than we should pass NotNullEngine as constructor argument - // that would nicely remove checking on compilation time. - enum OperationMode {Default, NotNullEngine}; - inline QScriptIsolate(const QV8Engine *engine, const OperationMode mode = Default) - : m_engine(engine) - , m_mode(mode) - { - if (m_mode == NotNullEngine || m_engine) { - Q_ASSERT(m_engine); - m_engine->context()->Enter(); - } - } - - inline ~QScriptIsolate() - { - if (m_mode == NotNullEngine || m_engine) { - m_engine->context()->Exit(); - } - } - -private: - Q_DISABLE_COPY(QScriptIsolate) - const QV8Engine *m_engine; - const OperationMode m_mode; -}; - - -QT_END_NAMESPACE - -#endif // APIPREAMBLE_P_H diff --git a/src/qml/qml/v8/qscriptoriginalglobalobject_p.h b/src/qml/qml/v8/qscriptoriginalglobalobject_p.h deleted file mode 100644 index 2ecdbdac91..0000000000 --- a/src/qml/qml/v8/qscriptoriginalglobalobject_p.h +++ /dev/null @@ -1,177 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSCRIPTORIGINALGLOBALOBJECT_P_H -#define QSCRIPTORIGINALGLOBALOBJECT_P_H - -#include "QtCore/qglobal.h" -#include "qjsvalue_p.h" - -#include <private/qv8_p.h> - -QT_BEGIN_NAMESPACE - -class QV8Engine; - -/*! - \internal - This class is a workaround for missing V8 API functionality. This class keeps all important - properties of an original (default) global object, so we can use it even if the global object was - changed. - - FIXME this class is a container for workarounds :-) it should be replaced by proper API calls. - - The class have to be created on the QV8Engine creation time (before any change got applied to - global object). - - \attention All methods (apart from constructor) assumes that a context and a scope are prepared correctly. -*/ -class QScriptOriginalGlobalObject -{ -public: - inline QScriptOriginalGlobalObject() {} - inline void init(v8::Handle<v8::Context> context); - inline void destroy(); - - inline QJSValuePrivate::PropertyFlags getPropertyFlags(v8::Handle<v8::Object> object, v8::Handle<v8::Value> property); - inline v8::Local<v8::Object> getOwnPropertyDescriptor(v8::Handle<v8::Object> object, v8::Handle<v8::Value> property) const; - inline bool strictlyEquals(v8::Handle<v8::Object> object); -private: - Q_DISABLE_COPY(QScriptOriginalGlobalObject) - - // Copy of constructors and prototypes used in isType functions. - v8::Persistent<v8::Function> m_ownPropertyDescriptor; - v8::Persistent<v8::Object> m_globalObject; -}; - -void QScriptOriginalGlobalObject::init(v8::Handle<v8::Context> context) -{ - // Please notice that engine is not fully initialized at this point. - - v8::Context::Scope contextScope(context); - - v8::HandleScope scope; - - m_globalObject = v8::Persistent<v8::Object>::New(context->Global()); - - v8::Local<v8::Object> objectConstructor = m_globalObject->Get(v8::String::New("Object"))->ToObject(); - Q_ASSERT(objectConstructor->IsObject()); - { // Initialize m_ownPropertyDescriptor. - v8::Local<v8::Value> ownPropertyDescriptor = objectConstructor->Get(v8::String::New("getOwnPropertyDescriptor")); - Q_ASSERT(!ownPropertyDescriptor.IsEmpty()); - m_ownPropertyDescriptor = v8::Persistent<v8::Function>::New(v8::Local<v8::Function>::Cast(ownPropertyDescriptor)); - } -} - -/*! - \internal - QScriptOriginalGlobalObject lives as long as QV8Engine that keeps it. In ~QSEP - the v8 context is removed, so we need to remove our handlers before. to break this dependency - destroy method should be called before or insight QSEP destructor. -*/ -inline void QScriptOriginalGlobalObject::destroy() -{ - m_ownPropertyDescriptor.Dispose(); - m_globalObject.Dispose(); - // After this line this instance is unusable. -} - -inline QJSValuePrivate::PropertyFlags QScriptOriginalGlobalObject::getPropertyFlags(v8::Handle<v8::Object> object, v8::Handle<v8::Value> property) -{ - Q_ASSERT(object->IsObject()); - Q_ASSERT(!property.IsEmpty()); - v8::Local<v8::Object> descriptor = getOwnPropertyDescriptor(object, property); - if (descriptor.IsEmpty()) { -// // Property isn't owned by this object. -// if (!(mode & QScriptValue::ResolvePrototype)) -// return 0; - v8::Local<v8::Value> prototype = object->GetPrototype(); - if (prototype->IsNull()) - return 0; - return getPropertyFlags(v8::Local<v8::Object>::Cast(prototype), property); - } - v8::Local<v8::String> writableName = v8::String::New("writable"); - v8::Local<v8::String> configurableName = v8::String::New("configurable"); - v8::Local<v8::String> enumerableName = v8::String::New("enumerable"); -// v8::Local<v8::String> getName = v8::String::New("get"); -// v8::Local<v8::String> setName = v8::String::New("set"); - - unsigned flags = 0; - - if (!descriptor->Get(configurableName)->BooleanValue()) - flags |= QJSValuePrivate::Undeletable; - if (!descriptor->Get(enumerableName)->BooleanValue()) - flags |= QJSValuePrivate::SkipInEnumeration; - - //"writable" is only a property of the descriptor if it is not an accessor - if (descriptor->Has(writableName)) { - if (!descriptor->Get(writableName)->BooleanValue()) - flags |= QJSValuePrivate::ReadOnly; - } else { -// if (descriptor->Get(getName)->IsObject()) -// flags |= QScriptValue::PropertyGetter; -// if (descriptor->Get(setName)->IsObject()) -// flags |= QScriptValue::PropertySetter; - } - - return QJSValuePrivate::PropertyFlag(flags); -} - -inline v8::Local<v8::Object> QScriptOriginalGlobalObject::getOwnPropertyDescriptor(v8::Handle<v8::Object> object, v8::Handle<v8::Value> property) const -{ - Q_ASSERT(object->IsObject()); - Q_ASSERT(!property.IsEmpty()); - // FIXME do we need try catch here? - v8::Handle<v8::Value> argv[] = {object, property}; - v8::Local<v8::Value> descriptor = m_ownPropertyDescriptor->Call(m_globalObject, /* argc */ 2, argv); - if (descriptor.IsEmpty() || !descriptor->IsObject()) - return v8::Local<v8::Object>(); - return v8::Local<v8::Object>::Cast(descriptor); -} - -inline bool QScriptOriginalGlobalObject::strictlyEquals(v8::Handle<v8::Object> object) -{ - return m_globalObject->GetPrototype()->StrictEquals(object); -} - -QT_END_NAMESPACE - -#endif diff --git a/src/qml/qml/v8/qscriptshareddata_p.h b/src/qml/qml/v8/qscriptshareddata_p.h deleted file mode 100644 index 70289cba46..0000000000 --- a/src/qml/qml/v8/qscriptshareddata_p.h +++ /dev/null @@ -1,169 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#ifndef QSCRIPTSHAREDDATA_P_H -#define QSCRIPTSHAREDDATA_P_H - -#include "qglobal.h" -#include "qshareddata.h" - -QT_BEGIN_NAMESPACE - -/*! - \internal - This class should have the same interface as the QSharedData, but implementation doesn't - need to be thread safe, so atomic ref count was replaced by normal integer value. -*/ -class QScriptSharedData -{ -public: - class ReferenceCounter { - // FIXME shouldn't it be uint or something longer? - mutable int m_ref; - ReferenceCounter(int ref) : m_ref(ref) {} - ~ReferenceCounter() { Q_ASSERT_X(!m_ref, Q_FUNC_INFO, "Memory problem found"); } - public: - bool ref() { return ++m_ref; } - bool deref() { return --m_ref; } - friend class QScriptSharedData; - }; - - ReferenceCounter ref; - inline QScriptSharedData() : ref(0) { } - -private: - Q_DISABLE_COPY(QScriptSharedData) -}; - - -template <class T> class QScriptPassPointer; - -// FIXME: that could be reimplemented to not check for a null value. -template<class T> -class QScriptSharedDataPointer : public QExplicitlySharedDataPointer<T> -{ -public: - inline QScriptSharedDataPointer() {} - explicit QScriptSharedDataPointer(QScriptPassPointer<T> data) : QExplicitlySharedDataPointer<T>(data.give()) {} - explicit QScriptSharedDataPointer(T *data) : QExplicitlySharedDataPointer<T>(data) {} - - inline QScriptSharedDataPointer<T> &operator=(const QScriptPassPointer<T> &other) - { - this->QExplicitlySharedDataPointer<T>::operator =(other.give()); - return *this; - } - inline QScriptSharedDataPointer<T> &operator=(T *other) - { - this->QExplicitlySharedDataPointer<T>::operator =(other); - return *this; - } -}; - -// FIXME: that could be reimplemented to not check for a null value. -template <class T> -class QScriptPassPointer { -public: - QScriptPassPointer(T *data) : m_ptr(data) {} - inline QScriptPassPointer() { m_ptr = 0; } - inline QScriptPassPointer(const QScriptPassPointer<T> &other) : m_ptr(other.give()) {} - inline ~QScriptPassPointer() { Q_ASSERT_X(!m_ptr, Q_FUNC_INFO, "Ownership of the QScriptPassPointer hasn't been taken"); } - - inline T &operator*() const { return *m_ptr; } - inline T *operator->() { return m_ptr; } - inline T *operator->() const { return m_ptr; } - inline T *data() const { return m_ptr; } - inline const T *constData() const { return m_ptr; } - - inline bool operator==(const QScriptPassPointer<T> &other) const { return m_ptr == other.m_ptr; } - inline bool operator!=(const QScriptPassPointer<T> &other) const { return m_ptr != other.m_ptr; } - inline bool operator==(const QScriptSharedDataPointer<T> &other) const { return m_ptr == other.m_ptr; } - inline bool operator!=(const QScriptSharedDataPointer<T> &other) const { return m_ptr != other.m_ptr; } - inline bool operator==(const T *ptr) const { return m_ptr == ptr; } - inline bool operator!=(const T *ptr) const { return m_ptr != ptr; } - - inline operator bool () const { return m_ptr != 0; } - inline bool operator!() const { return !m_ptr; } - - inline QScriptPassPointer<T> & operator=(const QScriptPassPointer<T> &other) - { - if (other.m_ptr != m_ptr) { - if (m_ptr) - delete m_ptr; - m_ptr = other.give(); - } - return *this; - } - - inline QScriptPassPointer &operator=(T *other) - { - if (other != m_ptr) { - if (m_ptr) - delete m_ptr; - m_ptr = other; - } - return *this; - } - - inline T* give() const - { - T* result = m_ptr; - m_ptr = 0; - return result; - } - -private: - mutable T* m_ptr; -}; - -QT_END_NAMESPACE - -#endif // QSCRIPTSHAREDDATA_P_H diff --git a/src/qml/qml/v8/qscripttools_p.h b/src/qml/qml/v8/qscripttools_p.h deleted file mode 100644 index 29adfa4ef9..0000000000 --- a/src/qml/qml/v8/qscripttools_p.h +++ /dev/null @@ -1,86 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - - -#ifndef QSCRIPTTOOLS_P_H -#define QSCRIPTTOOLS_P_H - -#include <private/qintrusivelist_p.h> - -QT_BEGIN_NAMESPACE - -template<class N, QIntrusiveListNode N::*member> -class QScriptIntrusiveList : public QIntrusiveList<N, member> -{ -public: - inline void insert(N *n); - inline void remove(N *n); -}; - -template<class N, QIntrusiveListNode N::*member> -void QScriptIntrusiveList<N, member>::insert(N *n) -{ - Q_ASSERT_X(!this->contains(n), Q_FUNC_INFO, "Can't insert a value which is in the list already"); - Q_ASSERT_X(!(n->*member).isInList(), Q_FUNC_INFO, "Can't insert a value which is in another list"); - QIntrusiveList<N, member>::insert(n); -} - -template<class N, QIntrusiveListNode N::*member> -void QScriptIntrusiveList<N, member>::remove(N *n) -{ - Q_ASSERT_X(this->contains(n), Q_FUNC_INFO, "Can't remove a value which is not in the list"); - QIntrusiveList<N, member>::remove(n); -} - -QT_END_NAMESPACE - -#endif //QSCRIPTTOOLS_P_H diff --git a/src/qml/qml/v8/qv4domerrors.cpp b/src/qml/qml/v8/qv4domerrors.cpp new file mode 100644 index 0000000000..63c79f85c2 --- /dev/null +++ b/src/qml/qml/v8/qv4domerrors.cpp @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qv4domerrors_p.h" +#include "qv4object_p.h" + +QT_BEGIN_NAMESPACE + +using namespace QV4; + +void qt_add_domexceptions(ExecutionEngine *e) +{ + Object *domexception = e->newObject(); + domexception->defineReadonlyProperty(e, QStringLiteral("INDEX_SIZE_ERR"), Value::fromInt32(DOMEXCEPTION_INDEX_SIZE_ERR)); + domexception->defineReadonlyProperty(e, QStringLiteral("DOMSTRING_SIZE_ERR"), Value::fromInt32(DOMEXCEPTION_DOMSTRING_SIZE_ERR)); + domexception->defineReadonlyProperty(e, QStringLiteral("HIERARCHY_REQUEST_ERR"), Value::fromInt32(DOMEXCEPTION_HIERARCHY_REQUEST_ERR)); + domexception->defineReadonlyProperty(e, QStringLiteral("WRONG_DOCUMENT_ERR"), Value::fromInt32(DOMEXCEPTION_WRONG_DOCUMENT_ERR)); + domexception->defineReadonlyProperty(e, QStringLiteral("INVALID_CHARACTER_ERR"), Value::fromInt32(DOMEXCEPTION_INVALID_CHARACTER_ERR)); + domexception->defineReadonlyProperty(e, QStringLiteral("NO_DATA_ALLOWED_ERR"), Value::fromInt32(DOMEXCEPTION_NO_DATA_ALLOWED_ERR)); + domexception->defineReadonlyProperty(e, QStringLiteral("NO_MODIFICATION_ALLOWED_ERR"), Value::fromInt32(DOMEXCEPTION_NO_MODIFICATION_ALLOWED_ERR)); + domexception->defineReadonlyProperty(e, QStringLiteral("NOT_FOUND_ERR"), Value::fromInt32(DOMEXCEPTION_NOT_FOUND_ERR)); + domexception->defineReadonlyProperty(e, QStringLiteral("NOT_SUPPORTED_ERR"), Value::fromInt32(DOMEXCEPTION_NOT_SUPPORTED_ERR)); + domexception->defineReadonlyProperty(e, QStringLiteral("INUSE_ATTRIBUTE_ERR"), Value::fromInt32(DOMEXCEPTION_INUSE_ATTRIBUTE_ERR)); + domexception->defineReadonlyProperty(e, QStringLiteral("INVALID_STATE_ERR"), Value::fromInt32(DOMEXCEPTION_INVALID_STATE_ERR)); + domexception->defineReadonlyProperty(e, QStringLiteral("SYNTAX_ERR"), Value::fromInt32(DOMEXCEPTION_SYNTAX_ERR)); + domexception->defineReadonlyProperty(e, QStringLiteral("INVALID_MODIFICATION_ERR"), Value::fromInt32(DOMEXCEPTION_INVALID_MODIFICATION_ERR)); + domexception->defineReadonlyProperty(e, QStringLiteral("NAMESPACE_ERR"), Value::fromInt32(DOMEXCEPTION_NAMESPACE_ERR)); + domexception->defineReadonlyProperty(e, QStringLiteral("INVALID_ACCESS_ERR"), Value::fromInt32(DOMEXCEPTION_INVALID_ACCESS_ERR)); + domexception->defineReadonlyProperty(e, QStringLiteral("VALIDATION_ERR"), Value::fromInt32(DOMEXCEPTION_VALIDATION_ERR)); + domexception->defineReadonlyProperty(e, QStringLiteral("TYPE_MISMATCH_ERR"), Value::fromInt32(DOMEXCEPTION_TYPE_MISMATCH_ERR)); + e->globalObject->defineDefaultProperty(e->current, QStringLiteral("DOMException"), Value::fromObject(domexception)); +} + +QT_END_NAMESPACE diff --git a/src/qml/qml/v8/qv8domerrors_p.h b/src/qml/qml/v8/qv4domerrors_p.h index 8fd1ccb6d6..ed38886e15 100644 --- a/src/qml/qml/v8/qv8domerrors_p.h +++ b/src/qml/qml/v8/qv4domerrors_p.h @@ -76,14 +76,19 @@ QT_BEGIN_NAMESPACE #define DOMEXCEPTION_VALIDATION_ERR 16 #define DOMEXCEPTION_TYPE_MISMATCH_ERR 17 -#define V8THROW_DOM(error, string) { \ - v8::Local<v8::Value> v = v8::Exception::Error(v8::String::New(string)); \ - v->ToObject()->Set(v8::String::New("code"), v8::Integer::New(error)); \ - v8::ThrowException(v); \ - return v8::Handle<v8::Value>(); \ +#define V4THROW_DOM(error, string) { \ + QV4::Value v = QV4::Value::fromString(ctx, QStringLiteral(string)); \ + QV4::Object *ex = ctx->engine->newErrorObject(v); \ + ex->put(ctx->engine->newIdentifier(QStringLiteral("code")), QV4::Value::fromInt32(error)); \ + ctx->throwError(QV4::Value::fromObject(ex)); \ } -class QV8Engine; -void qt_add_domexceptions(QV8Engine *engine); + +namespace QV4 { +struct ExecutionEngine; +} + + +void qt_add_domexceptions(QV4::ExecutionEngine *e); QT_END_NAMESPACE diff --git a/src/qml/qml/v8/qv8stringwrapper.cpp b/src/qml/qml/v8/qv4sqlerrors.cpp index f069c57b52..bd5a9fdc83 100644 --- a/src/qml/qml/v8/qv8stringwrapper.cpp +++ b/src/qml/qml/v8/qv4sqlerrors.cpp @@ -39,40 +39,26 @@ ** ****************************************************************************/ -#include "qv8stringwrapper_p.h" -#include "qjsconverter_p.h" -#include "qjsconverter_impl_p.h" +#include "qv4sqlerrors_p.h" +#include "private/qv4engine_p.h" +#include "private/qv4object_p.h" QT_BEGIN_NAMESPACE -QV8StringWrapper::QV8StringWrapper() -{ -} - -QV8StringWrapper::~QV8StringWrapper() -{ -} - -void QV8StringWrapper::init() -{ -} - -void QV8StringWrapper::destroy() -{ -} - -v8::Local<v8::String> QV8StringWrapper::toString(const QString &qstr) -{ - return QJSConverter::toString(qstr); -} +using namespace QV4; -QString QV8StringWrapper::toString(v8::Handle<v8::String> jsstr) +void qt_add_sqlexceptions(QV4::ExecutionEngine *engine) { - if (jsstr.IsEmpty()) { - return QString(); - } else { - return QJSConverter::toString(jsstr); - } + Object *sqlexception = engine->newObject(); + sqlexception->defineReadonlyProperty(engine, QStringLiteral("UNKNOWN_ERR"), Value::fromInt32(SQLEXCEPTION_UNKNOWN_ERR)); + sqlexception->defineReadonlyProperty(engine, QStringLiteral("DATABASE_ERR"), Value::fromInt32(SQLEXCEPTION_DATABASE_ERR)); + sqlexception->defineReadonlyProperty(engine, QStringLiteral("VERSION_ERR"), Value::fromInt32(SQLEXCEPTION_VERSION_ERR)); + sqlexception->defineReadonlyProperty(engine, QStringLiteral("TOO_LARGE_ERR"), Value::fromInt32(SQLEXCEPTION_TOO_LARGE_ERR)); + sqlexception->defineReadonlyProperty(engine, QStringLiteral("QUOTA_ERR"), Value::fromInt32(SQLEXCEPTION_QUOTA_ERR)); + sqlexception->defineReadonlyProperty(engine, QStringLiteral("SYNTAX_ERR"), Value::fromInt32(SQLEXCEPTION_SYNTAX_ERR)); + sqlexception->defineReadonlyProperty(engine, QStringLiteral("CONSTRAINT_ERR"), Value::fromInt32(SQLEXCEPTION_CONSTRAINT_ERR)); + sqlexception->defineReadonlyProperty(engine, QStringLiteral("TIMEOUT_ERR"), Value::fromInt32(SQLEXCEPTION_TIMEOUT_ERR)); + engine->globalObject->defineDefaultProperty(engine->current, QStringLiteral("SQLException"), Value::fromObject(sqlexception)); } QT_END_NAMESPACE diff --git a/src/qml/qml/v8/qv8sqlerrors_p.h b/src/qml/qml/v8/qv4sqlerrors_p.h index 8a612d69ab..0433d534f9 100644 --- a/src/qml/qml/v8/qv8sqlerrors_p.h +++ b/src/qml/qml/v8/qv4sqlerrors_p.h @@ -65,8 +65,11 @@ QT_BEGIN_NAMESPACE #define SQLEXCEPTION_CONSTRAINT_ERR 7 #define SQLEXCEPTION_TIMEOUT_ERR 8 -class QV8Engine; -void qt_add_sqlexceptions(QV8Engine *engine); +namespace QV4 { +struct ExecutionEngine; +} + +void qt_add_sqlexceptions(QV4::ExecutionEngine *engine); QT_END_NAMESPACE diff --git a/src/qml/qml/v8/qv8_p.h b/src/qml/qml/v8/qv8_p.h deleted file mode 100644 index dc5ecc31bc..0000000000 --- a/src/qml/qml/v8/qv8_p.h +++ /dev/null @@ -1,42 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <private/v8.h> diff --git a/src/qml/qml/v8/qv8bindings.cpp b/src/qml/qml/v8/qv8bindings.cpp deleted file mode 100644 index 757d9d9cf6..0000000000 --- a/src/qml/qml/v8/qv8bindings.cpp +++ /dev/null @@ -1,334 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qv8bindings_p.h" - -#include <private/qv8_p.h> -#include <private/qqmlbinding_p.h> -#include <private/qqmlcompiler_p.h> -#include <private/qqmlproperty_p.h> -#include <private/qqmlexpression_p.h> -#include <private/qobject_p.h> -#include <private/qqmltrace_p.h> -#include <private/qqmlprofilerservice_p.h> - -QT_BEGIN_NAMESPACE - -QQmlAbstractBinding::VTable QV8Bindings_Binding_vtable = { - QV8Bindings::Binding::destroy, - QQmlAbstractBinding::default_expression, - QV8Bindings::Binding::propertyIndex, - QV8Bindings::Binding::object, - QV8Bindings::Binding::setEnabled, - QV8Bindings::Binding::update, - QV8Bindings::Binding::retargetBinding -}; - -static QQmlJavaScriptExpression::VTable QV8Bindings_Binding_jsvtable = { - QV8Bindings::Binding::expressionIdentifier, - QV8Bindings::Binding::expressionChanged -}; - -QV8Bindings::Binding::Binding() -: QQmlJavaScriptExpression(&QV8Bindings_Binding_jsvtable), QQmlAbstractBinding(V8), parent(0) -{ -} - -void QV8Bindings::Binding::setEnabled(QQmlAbstractBinding *_This, bool e, - QQmlPropertyPrivate::WriteFlags flags) -{ - QV8Bindings::Binding *This = static_cast<QV8Bindings::Binding *>(_This); - - if (This->enabledFlag() != e) { - This->setEnabledFlag(e); - - if (e) This->update(flags); - } -} - -void QV8Bindings::refresh() -{ - int count = functions()->Length(); - for (int ii = 0; ii < count; ++ii) - bindings[ii].refresh(); -} - -void QV8Bindings::Binding::refresh() -{ - update(); -} - -int QV8Bindings::Binding::propertyIndex(const QQmlAbstractBinding *_This) -{ - const QV8Bindings::Binding *This = static_cast<const QV8Bindings::Binding *>(_This); - if (This->target.hasValue()) return This->target.constValue()->targetProperty; - else return This->instruction->property.encodedIndex(); -} - -QObject *QV8Bindings::Binding::object(const QQmlAbstractBinding *_This) -{ - const QV8Bindings::Binding *This = static_cast<const QV8Bindings::Binding *>(_This); - - if (This->target.hasValue()) return This->target.constValue()->target; - else return *This->target; -} - -QObject *QV8Bindings::Binding::object() const -{ - if (target.hasValue()) return target.constValue()->target; - else return *target; -} - -void QV8Bindings::Binding::retargetBinding(QQmlAbstractBinding *_This, QObject *t, int i) -{ - QV8Bindings::Binding *This = static_cast<QV8Bindings::Binding *>(_This); - - This->target.value().target = t; - This->target.value().targetProperty = i; -} - -void QV8Bindings::Binding::update(QQmlAbstractBinding *_This, QQmlPropertyPrivate::WriteFlags flags) -{ - QV8Bindings::Binding *This = static_cast<QV8Bindings::Binding *>(_This); - This->update(flags); -} - -void QV8Bindings::Binding::dump() -{ - qWarning() << parent->url() << instruction->line << instruction->column; -} - -void QV8Bindings::Binding::update(QQmlPropertyPrivate::WriteFlags flags) -{ - if (!enabledFlag()) - return; - - QQmlContextData *context = parent->context(); - - if (!context || !context->isValid()) - return; - - // Check that the target has not been deleted - if (QQmlData::wasDeleted(object())) - return; - - int lineNo = qmlSourceCoordinate(instruction->line); - int columnNo = qmlSourceCoordinate(instruction->column); - - QQmlTrace trace("V8 Binding Update"); - trace.addDetail("URL", parent->url()); - trace.addDetail("Line", lineNo); - trace.addDetail("Column", columnNo); - - QQmlBindingProfiler prof(parent->urlString(), lineNo, columnNo, QQmlProfilerService::V8Binding); - - if (!updatingFlag()) { - setUpdatingFlag(true); - - QQmlEnginePrivate *ep = QQmlEnginePrivate::get(context->engine); - - bool isUndefined = false; - - DeleteWatcher watcher(this); - ep->referenceScarceResources(); - - v8::HandleScope handle_scope; - v8::Context::Scope scope(ep->v8engine()->context()); - v8::Local<v8::Value> result = - evaluate(context, - v8::Handle<v8::Function>::Cast(parent->functions()->Get(instruction->value)), - &isUndefined); - - trace.event("writing V8 result"); - bool needsErrorLocationData = false; - if (!watcher.wasDeleted() && !destroyedFlag() && !hasError()) { - typedef QQmlPropertyPrivate PP; - needsErrorLocationData = !PP::writeBinding(*target, instruction->property, context, this, result, - isUndefined, flags); - } - - if (!watcher.wasDeleted() && !destroyedFlag()) { - - if (needsErrorLocationData) - delayedError()->setErrorLocation(parent->url(), instruction->line, 0); - - if (hasError()) { - delayedError()->setErrorObject(object()); - if (!delayedError()->addError(ep)) ep->warning(this->error(context->engine)); - } else { - clearError(); - } - - setUpdatingFlag(false); - } - - ep->dereferenceScarceResources(); - - } else { - QQmlProperty p = QQmlPropertyPrivate::restore(*target, instruction->property, context); - QQmlAbstractBinding::printBindingLoopError(p); - } -} - -QString QV8Bindings::Binding::expressionIdentifier(QQmlJavaScriptExpression *e) -{ - Binding *This = static_cast<Binding *>(e); - return This->parent->urlString() + QLatin1Char(':') + - QString::number(qmlSourceCoordinate(This->instruction->line)); -} - -void QV8Bindings::Binding::expressionChanged(QQmlJavaScriptExpression *e) -{ - Binding *This = static_cast<Binding *>(e); - This->update(QQmlPropertyPrivate::DontRemoveBinding); -} - -void QV8Bindings::Binding::destroy(QQmlAbstractBinding *_This, QQmlAbstractBinding::DestroyMode mode) -{ - QV8Bindings::Binding *This = static_cast<QV8Bindings::Binding *>(_This); - - if (mode == QQmlAbstractBinding::DisconnectBinding) - This->clearGuards(); - - This->setEnabledFlag(false); - This->setDestroyedFlag(true); - This->removeFromObject(); - This->clear(); - This->clearError(); - This->parent->release(); -} - -QV8Bindings::QV8Bindings(QQmlCompiledData::V8Program *program, - quint16 line, - QQmlContextData *context) -: program(program), bindings(0), refCount(1) -{ - QV8Engine *engine = QQmlEnginePrivate::getV8Engine(context->engine); - - if (program->bindings.IsEmpty()) { - v8::HandleScope handle_scope; - v8::Context::Scope scope(engine->context()); - - v8::Local<v8::Script> script; - bool compileFailed = false; - { - v8::TryCatch try_catch; - const QByteArray &source = program->program; - script = engine->qmlModeCompile(source.constData(), source.length(), - program->cdata->name, line); - if (try_catch.HasCaught()) { - // The binding was not compiled. There are some exceptional cases which the - // expression rewriter does not rewrite properly (e.g., \r-terminated lines - // are not rewritten correctly but this bug is demed out-of-scope to fix for - // performance reasons; see QTBUG-24064). - compileFailed = true; - QQmlError error; - error.setDescription(QString(QLatin1String("Exception occurred during compilation of binding at line: %1")).arg(line)); - v8::Local<v8::Message> message = try_catch.Message(); - if (!message.IsEmpty()) - QQmlExpressionPrivate::exceptionToError(message, error); - QQmlEnginePrivate::get(engine->engine())->warning(error); - program->bindings = qPersistentNew(v8::Array::New()); - } - } - - if (!compileFailed) { - v8::Local<v8::Value> result = script->Run(engine->contextWrapper()->sharedContext()); - if (result->IsArray()) { - program->bindings = qPersistentNew(v8::Local<v8::Array>::Cast(result)); - program->program.clear(); // We don't need the source anymore - } - } - } - - int bindingsCount = functions()->Length(); - if (bindingsCount) bindings = new QV8Bindings::Binding[bindingsCount]; - - setContext(context); -} - -QV8Bindings::~QV8Bindings() -{ - program = 0; - - delete [] bindings; - bindings = 0; -} - -QQmlAbstractBinding * -QV8Bindings::configBinding(QObject *target, QObject *scope, - const QQmlInstruction::instr_assignBinding *i) -{ - if (!bindings) // initialization failed. - return 0; - - QV8Bindings::Binding *rv = bindings + i->value; - - rv->instruction = i; - rv->target = target; - rv->setScopeObject(scope); - rv->setUseSharedContext(true); - rv->setNotifyOnValueChanged(true); - rv->parent = this; - - if (!i->isFallback) - addref(); // This is decremented in Binding::destroy() - - return rv; -} - -const QUrl &QV8Bindings::url() const -{ - return program->cdata->url; -} - -const QString &QV8Bindings::urlString() const -{ - return program->cdata->name; -} - -v8::Persistent<v8::Array> &QV8Bindings::functions() const -{ - return program->bindings; -} - - -QT_END_NAMESPACE diff --git a/src/qml/qml/v8/qv8bindings_p.h b/src/qml/qml/v8/qv8bindings_p.h deleted file mode 100644 index 98b367ac72..0000000000 --- a/src/qml/qml/v8/qv8bindings_p.h +++ /dev/null @@ -1,161 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QV8BINDINGS_P_H -#define QV8BINDINGS_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <private/qpointervaluepair_p.h> -#include <private/qqmlpropertycache_p.h> -#include <private/qqmlinstruction_p.h> -#include <private/qqmlexpression_p.h> -#include <private/qqmlcompiler_p.h> -#include <private/qflagpointer_p.h> -#include <private/qqmlbinding_p.h> - -QT_BEGIN_NAMESPACE - -class QQmlCompiledData; - -class QV8BindingsPrivate; -class QV8Bindings : public QQmlAbstractExpression -{ -public: - QV8Bindings(QQmlCompiledData::V8Program *, - quint16 line, - QQmlContextData *context); - virtual ~QV8Bindings(); - - QQmlAbstractBinding *configBinding(QObject *target, QObject *scope, - const QQmlInstruction::instr_assignBinding *); - - // Inherited from QQmlAbstractExpression - virtual void refresh(); - - struct Binding : public QQmlJavaScriptExpression, - public QQmlAbstractBinding { - Binding(); - - void update() { QQmlAbstractBinding::update(); } - void refresh(); - - // "Inherited" from QQmlJavaScriptExpression - static QString expressionIdentifier(QQmlJavaScriptExpression *); - static void expressionChanged(QQmlJavaScriptExpression *); - - // "Inherited" from QQmlAbstractBinding - static void destroy(QQmlAbstractBinding *, QQmlAbstractBinding::DestroyMode mode); - static int propertyIndex(const QQmlAbstractBinding *); - static QObject *object(const QQmlAbstractBinding *); - static void setEnabled(QQmlAbstractBinding *, bool, QQmlPropertyPrivate::WriteFlags); - static void update(QQmlAbstractBinding *, QQmlPropertyPrivate::WriteFlags); - static void retargetBinding(QQmlAbstractBinding *, QObject *, int); - - QObject *object() const; - void update(QQmlPropertyPrivate::WriteFlags flags); - - void dump(); - - QV8Bindings *parent; - - struct Retarget { - QObject *target; - int targetProperty; - }; - - // To save memory, we store flags inside the instruction pointer. - // target.flag1: destroyed - // instruction.flag1: enabled - // instruction.flag2: updating - QPointerValuePair<QObject, Retarget> target; - QFlagPointer<const QQmlInstruction::instr_assignBinding> instruction; - - inline bool destroyedFlag() const { return target.flag(); } - inline void setDestroyedFlag(bool v) { return target.setFlagValue(v); } - inline bool enabledFlag() const { return instruction.flag(); } - inline void setEnabledFlag(bool v) { instruction.setFlagValue(v); } - inline bool updatingFlag() const { return instruction.flag2(); } - inline void setUpdatingFlag(bool v) { instruction.setFlag2Value(v); } - }; - - inline void addref(); - inline void release(); - - QQmlAbstractBinding *binding(int index) const { return bindings + index; } - -private: - Q_DISABLE_COPY(QV8Bindings) - - const QUrl &url() const; - const QString &urlString() const; - v8::Persistent<v8::Array> &functions() const; - - QQmlCompiledData::V8Program *program; - Binding *bindings; - int refCount; -}; - -void QV8Bindings::addref() -{ - ++refCount; -} - -void QV8Bindings::release() -{ - if (0 == --refCount) - delete this; -} - -QT_END_NAMESPACE - -#endif // QV8BINDINGS_P_H - - diff --git a/src/qml/qml/v8/qv8contextwrapper.cpp b/src/qml/qml/v8/qv8contextwrapper.cpp deleted file mode 100644 index 630a3e5a7c..0000000000 --- a/src/qml/qml/v8/qv8contextwrapper.cpp +++ /dev/null @@ -1,430 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qv8contextwrapper_p.h" -#include "qv8engine_p.h" - -#include <private/qqmlengine_p.h> -#include <private/qqmlcontext_p.h> - -QT_BEGIN_NAMESPACE - -static QString internal(QLatin1String("You've stumbled onto an internal implementation detail " - "that should never have been exposed.")); - -class QV8ContextResource : public QV8ObjectResource -{ - V8_RESOURCE_TYPE(ContextType) - -public: - QV8ContextResource(QV8Engine *engine, QQmlContextData *context, QObject *scopeObject, bool ownsContext = false); - ~QV8ContextResource(); - - inline QQmlContextData *getContext() const; - inline QObject *getScopeObject() const; - - quint32 isSharedContext:1; - quint32 hasSubContexts:1; - quint32 readOnly:1; - quint32 ownsContext:1; - quint32 dummy:28; - - // This is a pretty horrible hack, and an abuse of external strings. When we create a - // sub-context (a context created by a Qt.include() in an external javascript file), - // we pass a specially crafted SubContext external string as the v8::Script::Data() to - // the script, which contains a pointer to the context. We can then access the - // v8::Script::Data() later on to resolve names and URLs against the sub-context instead - // of the main outer context. - struct SubContext : public v8::String::ExternalStringResource { - SubContext(QQmlContextData *context) : context(context) {} - QQmlGuardedContextData context; - - virtual const uint16_t* data() const { return (const uint16_t *)internal.constData(); } - virtual size_t length() const { return internal.length(); } - }; - -private: - QQmlGuardedContextData context; - QQmlGuard<QObject> scopeObject; - -}; - -QV8ContextResource::QV8ContextResource(QV8Engine *engine, QQmlContextData *context, QObject *scopeObject, bool ownsContext) -: QV8ObjectResource(engine), isSharedContext(false), hasSubContexts(false), readOnly(true), - ownsContext(ownsContext), context(context), scopeObject(scopeObject) -{ -} - -QV8ContextResource::~QV8ContextResource() -{ - if (context && ownsContext) - context->destroy(); -} - -// Returns the scope object -QObject *QV8ContextResource::getScopeObject() const -{ - if (isSharedContext) - return QQmlEnginePrivate::get(engine->engine())->sharedScope; - else - return scopeObject; -} - -// Returns the context, including resolving a subcontext -QQmlContextData *QV8ContextResource::getContext() const -{ - if (isSharedContext) - return QQmlEnginePrivate::get(engine->engine())->sharedContext; - - if (!hasSubContexts) - return context; - - v8::Local<v8::Value> callingdata = v8::Context::GetCallingScriptData(); - if (callingdata.IsEmpty() || !callingdata->IsString()) - return context; - - v8::Local<v8::String> callingstring = callingdata->ToString(); - Q_ASSERT(callingstring->IsExternal()); - Q_ASSERT(callingstring->GetExternalStringResource()); - - SubContext *sc = static_cast<SubContext *>(callingstring->GetExternalStringResource()); - return sc->context; -} - -QV8ContextWrapper::QV8ContextWrapper() -: m_engine(0) -{ -} - -QV8ContextWrapper::~QV8ContextWrapper() -{ -} - -void QV8ContextWrapper::destroy() -{ - qPersistentDispose(m_sharedContext); - qPersistentDispose(m_urlConstructor); - qPersistentDispose(m_constructor); -} - -void QV8ContextWrapper::init(QV8Engine *engine) -{ - m_engine = engine; - { - v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New(); - ft->InstanceTemplate()->SetHasExternalResource(true); - ft->InstanceTemplate()->SetFallbackPropertyHandler(Getter, Setter); - m_constructor = qPersistentNew<v8::Function>(ft->GetFunction()); - } - { - v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New(); - ft->InstanceTemplate()->SetHasExternalResource(true); - ft->InstanceTemplate()->SetFallbackPropertyHandler(NullGetter, NullSetter); - m_urlConstructor = qPersistentNew<v8::Function>(ft->GetFunction()); - } - { - v8::Local<v8::Object> sharedContext = m_constructor->NewInstance(); - QV8ContextResource *r = new QV8ContextResource(engine, 0, 0); - r->isSharedContext = true; - sharedContext->SetExternalResource(r); - m_sharedContext = qPersistentNew<v8::Object>(sharedContext); - } -} - -v8::Local<v8::Object> QV8ContextWrapper::qmlScope(QQmlContextData *ctxt, QObject *scope) -{ - // XXX NewInstance() should be optimized - v8::Local<v8::Object> rv = m_constructor->NewInstance(); - QV8ContextResource *r = new QV8ContextResource(m_engine, ctxt, scope); - rv->SetExternalResource(r); - return rv; -} - -v8::Local<v8::Object> QV8ContextWrapper::urlScope(const QUrl &url) -{ - QQmlContextData *context = new QQmlContextData; - context->url = url; - context->isInternal = true; - context->isJSContext = true; - - // XXX NewInstance() should be optimized - v8::Local<v8::Object> rv = m_urlConstructor->NewInstance(); - QV8ContextResource *r = new QV8ContextResource(m_engine, context, 0, true); - rv->SetExternalResource(r); - return rv; -} - -void QV8ContextWrapper::setReadOnly(v8::Handle<v8::Object> qmlglobal, bool readOnly) -{ - QV8ContextResource *resource = v8_resource_cast<QV8ContextResource>(qmlglobal); - Q_ASSERT(resource); - resource->readOnly = readOnly; -} - -void QV8ContextWrapper::addSubContext(v8::Handle<v8::Object> qmlglobal, v8::Handle<v8::Script> script, - QQmlContextData *ctxt) -{ - QV8ContextResource *resource = v8_resource_cast<QV8ContextResource>(qmlglobal); - Q_ASSERT(resource); - resource->hasSubContexts = true; - script->SetData(v8::String::NewExternal(new QV8ContextResource::SubContext(ctxt))); -} - -QQmlContextData *QV8ContextWrapper::callingContext() -{ - v8::Local<v8::Object> qmlglobal = v8::Context::GetCallingQmlGlobal(); - if (qmlglobal.IsEmpty()) return 0; - - QV8ContextResource *r = v8_resource_cast<QV8ContextResource>(qmlglobal); - return r?r->getContext():0; -} - -QQmlContextData *QV8ContextWrapper::context(v8::Handle<v8::Value> value) -{ - if (!value->IsObject()) - return 0; - - v8::Handle<v8::Object> qmlglobal = v8::Handle<v8::Object>::Cast(value); - QV8ContextResource *r = v8_resource_cast<QV8ContextResource>(qmlglobal); - return r?r->getContext():0; -} - -void QV8ContextWrapper::takeContextOwnership(v8::Handle<v8::Object> qmlglobal) -{ - QV8ContextResource *r = v8_resource_cast<QV8ContextResource>(qmlglobal); - r->ownsContext = true; -} - -v8::Handle<v8::Value> QV8ContextWrapper::NullGetter(v8::Local<v8::String>, - const v8::AccessorInfo &) -{ - // V8 will throw a ReferenceError if appropriate ("typeof" should not throw) - return v8::Handle<v8::Value>(); -} - -v8::Handle<v8::Value> QV8ContextWrapper::Getter(v8::Local<v8::String> property, - const v8::AccessorInfo &info) -{ - QV8ContextResource *resource = v8_resource_check<QV8ContextResource>(info.This()); - - // Its possible we could delay the calculation of the "actual" context (in the case - // of sub contexts) until it is definately needed. - QQmlContextData *context = resource->getContext(); - QQmlContextData *expressionContext = context; - - if (!context) - return v8::Undefined(); - - if (v8::Context::GetCallingQmlGlobal() != info.This()) - return v8::Handle<v8::Value>(); - - // Search type (attached property/enum/imported scripts) names - // while (context) { - // Search context properties - // Search scope object - // Search context object - // context = context->parent - // } - - QV8Engine *engine = resource->engine; - - QObject *scopeObject = resource->getScopeObject(); - - QHashedV8String propertystring(property); - - if (context->imports && QV8Engine::startsWithUpper(property)) { - // Search for attached properties, enums and imported scripts - QQmlTypeNameCache::Result r = context->imports->query(propertystring); - - if (r.isValid()) { - if (r.scriptIndex != -1) { - int index = r.scriptIndex; - if (index < context->importedScripts.count()) - return context->importedScripts.at(index); - else - return v8::Undefined(); - } else if (r.type) { - return engine->typeWrapper()->newObject(scopeObject, r.type); - } else if (r.importNamespace) { - return engine->typeWrapper()->newObject(scopeObject, context->imports, r.importNamespace); - } - Q_ASSERT(!"Unreachable"); - } - - // Fall through - } - - QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine->engine()); - QV8QObjectWrapper *qobjectWrapper = engine->qobjectWrapper(); - - while (context) { - // Search context properties - if (context->propertyNames) { - int propertyIdx = context->propertyNames->value(propertystring); - - if (propertyIdx != -1) { - - if (propertyIdx < context->idValueCount) { - - ep->captureProperty(&context->idValues[propertyIdx].bindings); - return engine->newQObject(context->idValues[propertyIdx]); - } else { - - QQmlContextPrivate *cp = context->asQQmlContextPrivate(); - - ep->captureProperty(context->asQQmlContext(), -1, - propertyIdx + cp->notifyIndex); - - const QVariant &value = cp->propertyValues.at(propertyIdx); - if (value.userType() == qMetaTypeId<QList<QObject*> >()) { - QQmlListProperty<QObject> prop(context->asQQmlContext(), (void*) qintptr(propertyIdx), - QQmlContextPrivate::context_count, - QQmlContextPrivate::context_at); - return engine->listWrapper()->newList(prop, qMetaTypeId<QQmlListProperty<QObject> >()); - } else { - return engine->fromVariant(cp->propertyValues.at(propertyIdx)); - } - } - } - } - - // Search scope object - if (scopeObject) { - v8::Handle<v8::Value> result = qobjectWrapper->getProperty(scopeObject, propertystring, - context, QV8QObjectWrapper::CheckRevision); - if (!result.IsEmpty()) return result; - } - scopeObject = 0; - - - // Search context object - if (context->contextObject) { - v8::Handle<v8::Value> result = qobjectWrapper->getProperty(context->contextObject, propertystring, - context, QV8QObjectWrapper::CheckRevision); - if (!result.IsEmpty()) return result; - } - - context = context->parent; - } - - expressionContext->unresolvedNames = true; - - // V8 will throw a ReferenceError if appropriate ("typeof" should not throw) - return v8::Handle<v8::Value>(); -} - -v8::Handle<v8::Value> QV8ContextWrapper::NullSetter(v8::Local<v8::String> property, - v8::Local<v8::Value>, - const v8::AccessorInfo &info) -{ - QV8ContextResource *resource = v8_resource_check<QV8ContextResource>(info.This()); - - QV8Engine *engine = resource->engine; - - if (!resource->readOnly) { - return v8::Handle<v8::Value>(); - } else { - QString error = QLatin1String("Invalid write to global property \"") + engine->toString(property) + - QLatin1Char('"'); - v8::ThrowException(v8::Exception::Error(engine->toString(error))); - return v8::Handle<v8::Value>(); - } -} - -v8::Handle<v8::Value> QV8ContextWrapper::Setter(v8::Local<v8::String> property, - v8::Local<v8::Value> value, - const v8::AccessorInfo &info) -{ - QV8ContextResource *resource = v8_resource_check<QV8ContextResource>(info.This()); - - // Its possible we could delay the calculation of the "actual" context (in the case - // of sub contexts) until it is definately needed. - QQmlContextData *context = resource->getContext(); - QQmlContextData *expressionContext = context; - - if (!context) - return v8::Undefined(); - - if (v8::Context::GetCallingQmlGlobal() != info.This()) - return v8::Handle<v8::Value>(); - - // See QV8ContextWrapper::Getter for resolution order - - QV8Engine *engine = resource->engine; - QObject *scopeObject = resource->getScopeObject(); - - QHashedV8String propertystring(property); - - QV8QObjectWrapper *qobjectWrapper = engine->qobjectWrapper(); - - while (context) { - // Search context properties - if (context->propertyNames && -1 != context->propertyNames->value(propertystring)) - return value; - - // Search scope object - if (scopeObject && - qobjectWrapper->setProperty(scopeObject, propertystring, context, value, QV8QObjectWrapper::CheckRevision)) - return value; - scopeObject = 0; - - // Search context object - if (context->contextObject && - qobjectWrapper->setProperty(context->contextObject, propertystring, context, value, - QV8QObjectWrapper::CheckRevision)) - return value; - - context = context->parent; - } - - expressionContext->unresolvedNames = true; - - if (!resource->readOnly) { - return v8::Handle<v8::Value>(); - } else { - QString error = QLatin1String("Invalid write to global property \"") + engine->toString(property) + - QLatin1Char('"'); - v8::ThrowException(v8::Exception::Error(engine->toString(error))); - return v8::Undefined(); - } -} - -QT_END_NAMESPACE diff --git a/src/qml/qml/v8/qv8contextwrapper_p.h b/src/qml/qml/v8/qv8contextwrapper_p.h deleted file mode 100644 index 3e14a019a7..0000000000 --- a/src/qml/qml/v8/qv8contextwrapper_p.h +++ /dev/null @@ -1,116 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QV8CONTEXTWRAPPER_P_H -#define QV8CONTEXTWRAPPER_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <QtCore/qglobal.h> -#include <private/qtqmlglobal_p.h> -#include <private/qv8_p.h> - -QT_BEGIN_NAMESPACE - -class QUrl; -class QObject; -class QV8Engine; -class QQmlContextData; -class Q_QML_PRIVATE_EXPORT QV8ContextWrapper -{ -public: - QV8ContextWrapper(); - ~QV8ContextWrapper(); - - void init(QV8Engine *); - void destroy(); - - v8::Local<v8::Object> qmlScope(QQmlContextData *ctxt, QObject *scope); - v8::Local<v8::Object> urlScope(const QUrl &); - - void setReadOnly(v8::Handle<v8::Object>, bool); - - void addSubContext(v8::Handle<v8::Object> qmlglobal, v8::Handle<v8::Script>, - QQmlContextData *ctxt); - - QQmlContextData *callingContext(); - QQmlContextData *context(v8::Handle<v8::Value>); - - inline v8::Handle<v8::Object> sharedContext() const; - - void takeContextOwnership(v8::Handle<v8::Object> qmlglobal); - -private: - static v8::Handle<v8::Value> NullGetter(v8::Local<v8::String> property, - const v8::AccessorInfo &info); - static v8::Handle<v8::Value> NullSetter(v8::Local<v8::String> property, - v8::Local<v8::Value> value, - const v8::AccessorInfo &info); - static v8::Handle<v8::Value> Getter(v8::Local<v8::String> property, - const v8::AccessorInfo &info); - static v8::Handle<v8::Value> Setter(v8::Local<v8::String> property, - v8::Local<v8::Value> value, - const v8::AccessorInfo &info); - - QV8Engine *m_engine; - v8::Persistent<v8::Function> m_constructor; - v8::Persistent<v8::Function> m_urlConstructor; - v8::Persistent<v8::Object> m_sharedContext; -}; - -v8::Handle<v8::Object> QV8ContextWrapper::sharedContext() const -{ - return m_sharedContext; -} - -QT_END_NAMESPACE - -#endif // QV8CONTEXTWRAPPER_P_H - diff --git a/src/qml/qml/v8/qv8debug_p.h b/src/qml/qml/v8/qv8debug_p.h index 6576839e42..87e4e13c7d 100644 --- a/src/qml/qml/v8/qv8debug_p.h +++ b/src/qml/qml/v8/qv8debug_p.h @@ -39,4 +39,4 @@ ** ****************************************************************************/ -#include <private/v8-debug.h> +//#include <private/v8-debug.h> diff --git a/src/qml/qml/v8/qv8domerrors.cpp b/src/qml/qml/v8/qv8domerrors.cpp deleted file mode 100644 index d3a36f75c1..0000000000 --- a/src/qml/qml/v8/qv8domerrors.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qv8domerrors_p.h" -#include "qv8engine_p.h" - -QT_BEGIN_NAMESPACE - -void qt_add_domexceptions(QV8Engine *engine) -{ - // DOM Exception - v8::PropertyAttribute attributes = (v8::PropertyAttribute)(v8::ReadOnly | v8::DontEnum | v8::DontDelete); - - v8::Local<v8::Object> domexception = v8::Object::New(); - domexception->Set(v8::String::New("INDEX_SIZE_ERR"), v8::Integer::New(DOMEXCEPTION_INDEX_SIZE_ERR), attributes); - domexception->Set(v8::String::New("DOMSTRING_SIZE_ERR"), v8::Integer::New(DOMEXCEPTION_DOMSTRING_SIZE_ERR), attributes); - domexception->Set(v8::String::New("HIERARCHY_REQUEST_ERR"), v8::Integer::New(DOMEXCEPTION_HIERARCHY_REQUEST_ERR), attributes); - domexception->Set(v8::String::New("WRONG_DOCUMENT_ERR"), v8::Integer::New(DOMEXCEPTION_WRONG_DOCUMENT_ERR), attributes); - domexception->Set(v8::String::New("INVALID_CHARACTER_ERR"), v8::Integer::New(DOMEXCEPTION_INVALID_CHARACTER_ERR), attributes); - domexception->Set(v8::String::New("NO_DATA_ALLOWED_ERR"), v8::Integer::New(DOMEXCEPTION_NO_DATA_ALLOWED_ERR), attributes); - domexception->Set(v8::String::New("NO_MODIFICATION_ALLOWED_ERR"), v8::Integer::New(DOMEXCEPTION_NO_MODIFICATION_ALLOWED_ERR), attributes); - domexception->Set(v8::String::New("NOT_FOUND_ERR"), v8::Integer::New(DOMEXCEPTION_NOT_FOUND_ERR), attributes); - domexception->Set(v8::String::New("NOT_SUPPORTED_ERR"), v8::Integer::New(DOMEXCEPTION_NOT_SUPPORTED_ERR), attributes); - domexception->Set(v8::String::New("INUSE_ATTRIBUTE_ERR"), v8::Integer::New(DOMEXCEPTION_INUSE_ATTRIBUTE_ERR), attributes); - domexception->Set(v8::String::New("INVALID_STATE_ERR"), v8::Integer::New(DOMEXCEPTION_INVALID_STATE_ERR), attributes); - domexception->Set(v8::String::New("SYNTAX_ERR"), v8::Integer::New(DOMEXCEPTION_SYNTAX_ERR), attributes); - domexception->Set(v8::String::New("INVALID_MODIFICATION_ERR"), v8::Integer::New(DOMEXCEPTION_INVALID_MODIFICATION_ERR), attributes); - domexception->Set(v8::String::New("NAMESPACE_ERR"), v8::Integer::New(DOMEXCEPTION_NAMESPACE_ERR), attributes); - domexception->Set(v8::String::New("INVALID_ACCESS_ERR"), v8::Integer::New(DOMEXCEPTION_INVALID_ACCESS_ERR), attributes); - domexception->Set(v8::String::New("VALIDATION_ERR"), v8::Integer::New(DOMEXCEPTION_VALIDATION_ERR), attributes); - domexception->Set(v8::String::New("TYPE_MISMATCH_ERR"), v8::Integer::New(DOMEXCEPTION_TYPE_MISMATCH_ERR), attributes); - engine->global()->Set(v8::String::New("DOMException"), domexception); -} - -QT_END_NAMESPACE diff --git a/src/qml/qml/v8/qv8engine.cpp b/src/qml/qml/v8/qv8engine.cpp index e80da46fc9..51605cead7 100644 --- a/src/qml/qml/v8/qv8engine.cpp +++ b/src/qml/qml/v8/qv8engine.cpp @@ -41,10 +41,7 @@ #include "qv8engine_p.h" -#include "qv8contextwrapper_p.h" -#include "qv8valuetypewrapper_p.h" -#include "qv8sequencewrapper_p.h" -#include "qv8include_p.h" +#include "qv4sequenceobject_p.h" #include "qjsengine_p.h" #include <private/qqmlbuiltinfunctions_p.h> @@ -55,14 +52,31 @@ #include <private/qqmlglobal_p.h> #include <private/qqmlmemoryprofiler_p.h> #include <private/qqmlplatform_p.h> +#include <private/qjsvalue_p.h> +#include <private/qqmltypewrapper_p.h> +#include <private/qqmlcontextwrapper_p.h> +#include <private/qqmlvaluetypewrapper_p.h> +#include <private/qqmllistwrapper_p.h> -#include "qscript_impl_p.h" -#include "qv8domerrors_p.h" -#include "qv8sqlerrors_p.h" +#include "qv4domerrors_p.h" +#include "qv4sqlerrors_p.h" #include <QtCore/qjsonarray.h> #include <QtCore/qjsonobject.h> #include <QtCore/qjsonvalue.h> +#include <QtCore/qdatetime.h> + +#include <private/qv4value_p.h> +#include <private/qv4dateobject_p.h> +#include <private/qv4objectiterator_p.h> +#include <private/qv4mm_p.h> +#include <private/qv4objectproto_p.h> +#include <private/qv4globalobject_p.h> +#include <private/qv4regexpobject_p.h> +#include <private/qv4variantobject_p.h> +#include <private/qv4script_p.h> +#include <private/qv4include_p.h> +#include <private/qv4jsonobject_p.h> Q_DECLARE_METATYPE(QList<int>) @@ -71,107 +85,25 @@ Q_DECLARE_METATYPE(QList<int>) // QQmlEngine is not available QT_BEGIN_NAMESPACE -static bool ObjectComparisonCallback(v8::Local<v8::Object> lhs, v8::Local<v8::Object> rhs) -{ - if (lhs == rhs) - return true; - - if (lhs.IsEmpty() || rhs.IsEmpty()) - return false; - QV8ObjectResource *lhsr = static_cast<QV8ObjectResource*>(lhs->GetExternalResource()); - QV8ObjectResource *rhsr = static_cast<QV8ObjectResource*>(rhs->GetExternalResource()); - - if (lhsr && rhsr) { - Q_ASSERT(lhsr->engine == rhsr->engine); - QV8ObjectResource::ResourceType lhst = lhsr->resourceType(); - QV8ObjectResource::ResourceType rhst = rhsr->resourceType(); - - switch (lhst) { - case QV8ObjectResource::ValueTypeType: - // a value type might be equal to a variant or another value type - if (rhst == QV8ObjectResource::ValueTypeType) { - return lhsr->engine->valueTypeWrapper()->isEqual(lhsr, lhsr->engine->valueTypeWrapper()->toVariant(rhsr)); - } else if (rhst == QV8ObjectResource::VariantType) { - return lhsr->engine->valueTypeWrapper()->isEqual(lhsr, lhsr->engine->variantWrapper()->toVariant(rhsr)); - } - break; - case QV8ObjectResource::VariantType: - // a variant might be equal to a value type or other variant. - if (rhst == QV8ObjectResource::VariantType) { - return lhsr->engine->variantWrapper()->toVariant(lhsr) == - lhsr->engine->variantWrapper()->toVariant(rhsr); - } else if (rhst == QV8ObjectResource::ValueTypeType) { - return rhsr->engine->valueTypeWrapper()->isEqual(rhsr, rhsr->engine->variantWrapper()->toVariant(lhsr)); - } - break; - case QV8ObjectResource::SequenceType: - // a sequence might be equal to itself. - if (rhst == QV8ObjectResource::SequenceType) { - return lhsr->engine->sequenceWrapper()->isEqual(lhsr, rhsr); - } - break; - default: - break; - } - } - - return false; -} - - -QV8Engine::QV8Engine(QJSEngine* qq, ContextOwnership ownership) +QV8Engine::QV8Engine(QJSEngine* qq) : q(qq) , m_engine(0) - , m_ownsV8Context(ownership == CreateNewContext) , m_xmlHttpRequestData(0) , m_listModelData(0) - , m_platform(0) - , m_application(0) { QML_MEMORY_SCOPE_STRING("QV8Engine::QV8Engine"); qMetaTypeId<QJSValue>(); qMetaTypeId<QList<int> >(); - QByteArray v8args = qgetenv("V8ARGS"); - // change default v8 behaviour to not relocate breakpoints across lines - if (!v8args.contains("breakpoint_relocation")) - v8args.append(" --nobreakpoint_relocation"); - v8::V8::SetFlagsFromString(v8args.constData(), v8args.length()); - - ensurePerThreadIsolate(); - - v8::HandleScope handle_scope; - m_context = (ownership == CreateNewContext) ? v8::Context::New() : v8::Persistent<v8::Context>::New(v8::Context::GetCurrent()); - qPersistentRegister(m_context); - m_originalGlobalObject.init(m_context); - v8::Context::Scope context_scope(m_context); - - v8::V8::SetUserObjectComparisonCallbackFunction(ObjectComparisonCallback); - QV8GCCallback::registerGcPrologueCallback(); - m_strongReferencer = qPersistentNew(v8::Object::New()); - - m_bindingFlagKey = qPersistentNew(v8::String::New("qml::binding")); + m_v4Engine = new QV4::ExecutionEngine; + m_v4Engine->v8Engine = this; - m_stringWrapper.init(); - m_contextWrapper.init(this); - m_qobjectWrapper.init(this); - m_typeWrapper.init(this); - m_listWrapper.init(this); - m_variantWrapper.init(this); - m_valueTypeWrapper.init(this); - m_sequenceWrapper.init(this); - m_jsonWrapper.init(this); - - { - v8::Handle<v8::Value> v = global()->Get(v8::String::New("Object"))->ToObject()->Get(v8::String::New("getOwnPropertyNames")); - m_getOwnPropertyNames = qPersistentNew<v8::Function>(v8::Handle<v8::Function>::Cast(v)); - } + QV4::QObjectWrapper::initializeBindings(m_v4Engine); } QV8Engine::~QV8Engine() { - Q_ASSERT_X(v8::Isolate::GetCurrent(), "QV8Engine::~QV8Engine()", "called after v8::Isolate has exited"); for (int ii = 0; ii < m_extensionData.count(); ++ii) delete m_extensionData[ii]; m_extensionData.clear(); @@ -181,105 +113,52 @@ QV8Engine::~QV8Engine() delete m_listModelData; m_listModelData = 0; - qPersistentDispose(m_freezeObject); - qPersistentDispose(m_getOwnPropertyNames); - - invalidateAllValues(); - - qPersistentDispose(m_strongReferencer); - - m_jsonWrapper.destroy(); - m_sequenceWrapper.destroy(); - m_valueTypeWrapper.destroy(); - m_variantWrapper.destroy(); - m_listWrapper.destroy(); - m_typeWrapper.destroy(); - m_qobjectWrapper.destroy(); - m_contextWrapper.destroy(); - m_stringWrapper.destroy(); - - qPersistentDispose(m_bindingFlagKey); - - m_originalGlobalObject.destroy(); - - if (m_ownsV8Context) - qPersistentDispose(m_context); -} - -QString QV8Engine::toStringStatic(v8::Handle<v8::Value> jsstr) -{ - return toStringStatic(jsstr->ToString()); -} - -QString QV8Engine::toStringStatic(v8::Handle<v8::String> jsstr) -{ - QString qstr; - qstr.resize(jsstr->Length()); - jsstr->Write((uint16_t*)qstr.data()); - return qstr; + delete m_v4Engine; } -QVariant QV8Engine::toVariant(v8::Handle<v8::Value> value, int typeHint) +QVariant QV8Engine::toVariant(const QV4::Value &value, int typeHint) { - if (value.IsEmpty()) + if (value.isEmpty()) return QVariant(); + if (QV4::VariantObject *v = value.as<QV4::VariantObject>()) + return v->data; + if (typeHint == QVariant::Bool) - return QVariant(value->BooleanValue()); + return QVariant(value.toBoolean()); if (typeHint == QMetaType::QJsonValue) - return QVariant::fromValue(jsonValueFromJS(value)); + return QVariant::fromValue(QV4::JsonObject::toJsonValue(value)); if (typeHint == qMetaTypeId<QJSValue>()) - return QVariant::fromValue(scriptValueFromInternal(value)); - - if (value->IsObject()) { - QV8ObjectResource *r = (QV8ObjectResource *)value->ToObject()->GetExternalResource(); - if (r) { - switch (r->resourceType()) { - case QV8ObjectResource::Context2DStyleType: - case QV8ObjectResource::Context2DPixelArrayType: - case QV8ObjectResource::SignalHandlerType: - case QV8ObjectResource::IncubatorType: - case QV8ObjectResource::VisualDataItemType: - case QV8ObjectResource::ContextType: - case QV8ObjectResource::XMLHttpRequestType: - case QV8ObjectResource::DOMNodeType: - case QV8ObjectResource::SQLDatabaseType: - case QV8ObjectResource::ListModelType: - case QV8ObjectResource::Context2DType: - case QV8ObjectResource::ParticleDataType: - case QV8ObjectResource::LocaleDataType: - case QV8ObjectResource::ChangeSetArrayType: - return QVariant(); - case QV8ObjectResource::TypeType: - return m_typeWrapper.toVariant(r); - case QV8ObjectResource::QObjectType: - return qVariantFromValue<QObject *>(m_qobjectWrapper.toQObject(r)); - case QV8ObjectResource::ListType: - return m_listWrapper.toVariant(r); - case QV8ObjectResource::VariantType: - return m_variantWrapper.toVariant(r); - case QV8ObjectResource::ValueTypeType: - return m_valueTypeWrapper.toVariant(r); - case QV8ObjectResource::SequenceType: - return m_sequenceWrapper.toVariant(r); - } - } else if (typeHint == QMetaType::QJsonObject - && !value->IsArray() && !value->IsFunction()) { - return QVariant::fromValue(jsonObjectFromJS(value)); - } - } - - if (value->IsArray()) { - v8::Handle<v8::Array> array = v8::Handle<v8::Array>::Cast(value); + return QVariant::fromValue(QJSValue(new QJSValuePrivate(m_v4Engine, value))); + + if (QV4::Object *object = value.asObject()) { + if (typeHint == QMetaType::QJsonObject + && !value.asArrayObject() && !value.asFunctionObject()) { + return QVariant::fromValue(QV4::JsonObject::toJsonObject(object)); + } else if (QV4::QObjectWrapper *wrapper = object->as<QV4::QObjectWrapper>()) { + return qVariantFromValue<QObject *>(wrapper->object()); + } else if (QV4::QmlContextWrapper *wrapper = object->as<QV4::QmlContextWrapper>()) { + return QVariant(); + } else if (QV4::QmlTypeWrapper *w = object->as<QV4::QmlTypeWrapper>()) { + return w->toVariant(); + } else if (QV4::QmlValueTypeWrapper *v = object->as<QV4::QmlValueTypeWrapper>()) { + return v->toVariant(); + } else if (QV4::QmlListWrapper *l = object->as<QV4::QmlListWrapper>()) { + return l->toVariant(); + } else if (object->isListType()) + return QV4::SequencePrototype::toVariant(object); + } + + if (QV4::ArrayObject *a = value.asArrayObject()) { if (typeHint == qMetaTypeId<QList<QObject *> >()) { QList<QObject *> list; - uint32_t length = array->Length(); + uint32_t length = a->arrayLength(); for (uint32_t ii = 0; ii < length; ++ii) { - v8::Local<v8::Value> arrayItem = array->Get(ii); - if (arrayItem->IsObject()) { - list << toQObject(arrayItem->ToObject()); + QV4::Value arrayItem = a->getIndexed(ii); + if (QV4::QObjectWrapper *qobjectWrapper = arrayItem.as<QV4::QObjectWrapper>()) { + list << qobjectWrapper->object(); } else { list << 0; } @@ -287,11 +166,11 @@ QVariant QV8Engine::toVariant(v8::Handle<v8::Value> value, int typeHint) return qVariantFromValue<QList<QObject*> >(list); } else if (typeHint == QMetaType::QJsonArray) { - return QVariant::fromValue(jsonArrayFromJS(value)); + return QVariant::fromValue(QV4::JsonObject::toJsonArray(a)); } bool succeeded = false; - QVariant retn = m_sequenceWrapper.toVariant(array, typeHint, &succeeded); + QVariant retn = QV4::SequencePrototype::toVariant(value, typeHint, &succeeded); if (succeeded) return retn; } @@ -299,36 +178,44 @@ QVariant QV8Engine::toVariant(v8::Handle<v8::Value> value, int typeHint) return toBasicVariant(value); } -static v8::Handle<v8::Array> arrayFromStringList(QV8Engine *engine, const QStringList &list) +static QV4::Value arrayFromStringList(QV8Engine *engine, const QStringList &list) { - v8::Context::Scope scope(engine->context()); - v8::Local<v8::Array> result = v8::Array::New(list.count()); - for (int ii = 0; ii < list.count(); ++ii) - result->Set(ii, engine->toString(list.at(ii))); - return result; + QV4::ExecutionEngine *e = QV8Engine::getV4(engine); + QV4::ArrayObject *a = e->newArrayObject(); + int len = list.count(); + a->arrayReserve(len); + for (int ii = 0; ii < len; ++ii) + a->arrayData[ii].value = QV4::Value::fromString(e->newString(list.at(ii))); + a->arrayDataLen = len; + a->setArrayLengthUnchecked(len); + return QV4::Value::fromObject(a); } -static v8::Handle<v8::Array> arrayFromVariantList(QV8Engine *engine, const QVariantList &list) +static QV4::Value arrayFromVariantList(QV8Engine *engine, const QVariantList &list) { - v8::Context::Scope scope(engine->context()); - v8::Local<v8::Array> result = v8::Array::New(list.count()); - for (int ii = 0; ii < list.count(); ++ii) - result->Set(ii, engine->fromVariant(list.at(ii))); - return result; + QV4::ExecutionEngine *e = QV8Engine::getV4(engine); + QV4::ArrayObject *a = e->newArrayObject(); + int len = list.count(); + a->arrayReserve(len); + for (int ii = 0; ii < len; ++ii) + a->arrayData[ii].value = engine->fromVariant(list.at(ii)); + a->arrayDataLen = len; + a->setArrayLengthUnchecked(len); + return QV4::Value::fromObject(a); } -static v8::Handle<v8::Object> objectFromVariantMap(QV8Engine *engine, const QVariantMap &map) +static QV4::Value objectFromVariantMap(QV8Engine *engine, const QVariantMap &map) { - v8::Context::Scope scope(engine->context()); - v8::Local<v8::Object> object = v8::Object::New(); + QV4::ExecutionEngine *e = QV8Engine::getV4(engine); + QV4::Object *o = e->newObject(); for (QVariantMap::ConstIterator iter = map.begin(); iter != map.end(); ++iter) - object->Set(engine->toString(iter.key()), engine->fromVariant(iter.value())); - return object; + o->put(e->newString(iter.key()), engine->fromVariant(iter.value())); + return QV4::Value::fromObject(o); } Q_CORE_EXPORT QString qt_regexp_toCanonical(const QString &, QRegExp::PatternSyntax); -v8::Handle<v8::Value> QV8Engine::fromVariant(const QVariant &variant) +QV4::Value QV8Engine::fromVariant(const QVariant &variant) { int type = variant.userType(); const void *ptr = variant.constData(); @@ -337,47 +224,47 @@ v8::Handle<v8::Value> QV8Engine::fromVariant(const QVariant &variant) switch (QMetaType::Type(type)) { case QMetaType::UnknownType: case QMetaType::Void: - return v8::Undefined(); + return QV4::Value::undefinedValue(); case QMetaType::Bool: - return v8::Boolean::New(*reinterpret_cast<const bool*>(ptr)); + return QV4::Value::fromBoolean(*reinterpret_cast<const bool*>(ptr)); case QMetaType::Int: - return v8::Integer::New(*reinterpret_cast<const int*>(ptr)); + return QV4::Value::fromInt32(*reinterpret_cast<const int*>(ptr)); case QMetaType::UInt: - return v8::Integer::NewFromUnsigned(*reinterpret_cast<const uint*>(ptr)); + return QV4::Value::fromUInt32(*reinterpret_cast<const uint*>(ptr)); case QMetaType::LongLong: - return v8::Number::New(*reinterpret_cast<const qlonglong*>(ptr)); + return QV4::Value::fromDouble(*reinterpret_cast<const qlonglong*>(ptr)); case QMetaType::ULongLong: - return v8::Number::New(*reinterpret_cast<const qulonglong*>(ptr)); + return QV4::Value::fromDouble(*reinterpret_cast<const qulonglong*>(ptr)); case QMetaType::Double: - return v8::Number::New(*reinterpret_cast<const double*>(ptr)); + return QV4::Value::fromDouble(*reinterpret_cast<const double*>(ptr)); case QMetaType::QString: - return m_stringWrapper.toString(*reinterpret_cast<const QString*>(ptr)); + return QV4::Value::fromString(m_v4Engine->current, *reinterpret_cast<const QString*>(ptr)); case QMetaType::Float: - return v8::Number::New(*reinterpret_cast<const float*>(ptr)); + return QV4::Value::fromDouble(*reinterpret_cast<const float*>(ptr)); case QMetaType::Short: - return v8::Integer::New(*reinterpret_cast<const short*>(ptr)); + return QV4::Value::fromInt32(*reinterpret_cast<const short*>(ptr)); case QMetaType::UShort: - return v8::Integer::NewFromUnsigned(*reinterpret_cast<const unsigned short*>(ptr)); + return QV4::Value::fromUInt32(*reinterpret_cast<const unsigned short*>(ptr)); case QMetaType::Char: - return v8::Integer::New(*reinterpret_cast<const char*>(ptr)); + return QV4::Value::fromInt32(*reinterpret_cast<const char*>(ptr)); case QMetaType::UChar: - return v8::Integer::NewFromUnsigned(*reinterpret_cast<const unsigned char*>(ptr)); + return QV4::Value::fromUInt32(*reinterpret_cast<const unsigned char*>(ptr)); case QMetaType::QChar: - return v8::Integer::New((*reinterpret_cast<const QChar*>(ptr)).unicode()); + return QV4::Value::fromInt32((*reinterpret_cast<const QChar*>(ptr)).unicode()); case QMetaType::QDateTime: - return v8::Date::New(qtDateTimeToJsDate(*reinterpret_cast<const QDateTime *>(ptr))); + return QV4::Value::fromObject(m_v4Engine->newDateObject(*reinterpret_cast<const QDateTime *>(ptr))); case QMetaType::QDate: - return v8::Date::New(qtDateTimeToJsDate(QDateTime(*reinterpret_cast<const QDate *>(ptr)))); + return QV4::Value::fromObject(m_v4Engine->newDateObject(QDateTime(*reinterpret_cast<const QDate *>(ptr)))); case QMetaType::QTime: - return v8::Date::New(qtDateTimeToJsDate(QDateTime(QDate(1970,1,1), *reinterpret_cast<const QTime *>(ptr)))); + return QV4::Value::fromObject(m_v4Engine->newDateObject(QDateTime(QDate(1970,1,1), *reinterpret_cast<const QTime *>(ptr)))); case QMetaType::QRegExp: - return QJSConverter::toRegExp(*reinterpret_cast<const QRegExp *>(ptr)); + return QV4::Value::fromObject(m_v4Engine->newRegExpObject(*reinterpret_cast<const QRegExp *>(ptr))); case QMetaType::QObjectStar: - return newQObject(*reinterpret_cast<QObject* const *>(ptr)); + return QV4::QObjectWrapper::wrap(m_v4Engine, *reinterpret_cast<QObject* const *>(ptr)); case QMetaType::QStringList: { bool succeeded = false; - v8::Handle<v8::Value> retn = m_sequenceWrapper.fromVariant(variant, &succeeded); + QV4::Value retn = QV4::SequencePrototype::fromVariant(m_v4Engine, variant, &succeeded); if (succeeded) return retn; return arrayFromStringList(this, *reinterpret_cast<const QStringList *>(ptr)); @@ -387,97 +274,63 @@ v8::Handle<v8::Value> QV8Engine::fromVariant(const QVariant &variant) case QMetaType::QVariantMap: return objectFromVariantMap(this, *reinterpret_cast<const QVariantMap *>(ptr)); case QMetaType::QJsonValue: - return jsonValueToJS(*reinterpret_cast<const QJsonValue *>(ptr)); + return QV4::JsonObject::fromJsonValue(m_v4Engine, *reinterpret_cast<const QJsonValue *>(ptr)); case QMetaType::QJsonObject: - return jsonObjectToJS(*reinterpret_cast<const QJsonObject *>(ptr)); + return QV4::JsonObject::fromJsonObject(m_v4Engine, *reinterpret_cast<const QJsonObject *>(ptr)); case QMetaType::QJsonArray: - return jsonArrayToJS(*reinterpret_cast<const QJsonArray *>(ptr)); + return QV4::JsonObject::fromJsonArray(m_v4Engine, *reinterpret_cast<const QJsonArray *>(ptr)); default: break; } if (QQmlValueType *vt = QQmlValueTypeFactory::valueType(type)) - return m_valueTypeWrapper.newValueType(variant, vt); + return QV4::QmlValueTypeWrapper::create(this, variant, vt); } else { if (type == qMetaTypeId<QQmlListReference>()) { typedef QQmlListReferencePrivate QDLRP; QDLRP *p = QDLRP::get((QQmlListReference*)ptr); if (p->object) { - return m_listWrapper.newList(p->property, p->propertyType); + return QV4::QmlListWrapper::create(this, p->property, p->propertyType); } else { - return v8::Null(); + return QV4::Value::nullValue(); } } else if (type == qMetaTypeId<QJSValue>()) { const QJSValue *value = reinterpret_cast<const QJSValue *>(ptr); QJSValuePrivate *valuep = QJSValuePrivate::get(*value); - if (valuep->assignEngine(this)) - return v8::Local<v8::Value>::New(*valuep); + return valuep->getValue(m_v4Engine); } else if (type == qMetaTypeId<QList<QObject *> >()) { // XXX Can this be made more by using Array as a prototype and implementing // directly against QList<QObject*>? const QList<QObject *> &list = *(QList<QObject *>*)ptr; - v8::Local<v8::Array> array = v8::Array::New(list.count()); + QV4::ArrayObject *a = m_v4Engine->newArrayObject(); + a->arrayReserve(list.count()); for (int ii = 0; ii < list.count(); ++ii) - array->Set(ii, newQObject(list.at(ii))); - return array; + a->arrayData[ii].value = QV4::QObjectWrapper::wrap(m_v4Engine, list.at(ii)); + a->arrayDataLen = list.count(); + a->setArrayLengthUnchecked(list.count()); + return QV4::Value::fromObject(a); } bool objOk; QObject *obj = QQmlMetaType::toQObject(variant, &objOk); if (objOk) - return newQObject(obj); + return QV4::QObjectWrapper::wrap(m_v4Engine, obj); bool succeeded = false; - v8::Handle<v8::Value> retn = m_sequenceWrapper.fromVariant(variant, &succeeded); + QV4::Value retn = QV4::SequencePrototype::fromVariant(m_v4Engine, variant, &succeeded); if (succeeded) return retn; if (QQmlValueType *vt = QQmlValueTypeFactory::valueType(type)) - return m_valueTypeWrapper.newValueType(variant, vt); + return QV4::QmlValueTypeWrapper::create(this, variant, vt); } // XXX TODO: To be compatible, we still need to handle: // + QObjectList // + QList<int> - return m_variantWrapper.newVariant(variant); -} - -// A handle scope and context must be entered -v8::Local<v8::Script> QV8Engine::qmlModeCompile(const QString &source, - const QString &fileName, - quint16 lineNumber) -{ - v8::Local<v8::String> v8source = m_stringWrapper.toString(source); - v8::Local<v8::String> v8fileName = m_stringWrapper.toString(fileName); - - v8::ScriptOrigin origin(v8fileName, v8::Integer::New(lineNumber - 1)); - - v8::Local<v8::Script> script = v8::Script::Compile(v8source, &origin, 0, v8::Handle<v8::String>(), - v8::Script::QmlMode); - - return script; -} - -// A handle scope and context must be entered. -// source can be either ascii or utf8. -v8::Local<v8::Script> QV8Engine::qmlModeCompile(const char *source, int sourceLength, - const QString &fileName, - quint16 lineNumber) -{ - if (sourceLength == -1) - sourceLength = int(strlen(source)); - - v8::Local<v8::String> v8source = v8::String::New(source, sourceLength); - v8::Local<v8::String> v8fileName = m_stringWrapper.toString(fileName); - - v8::ScriptOrigin origin(v8fileName, v8::Integer::New(lineNumber - 1)); - - v8::Local<v8::Script> script = v8::Script::Compile(v8source, &origin, 0, v8::Handle<v8::String>(), - v8::Script::QmlMode); - - return script; + return QV4::Value::fromObject(m_v4Engine->newVariantObject(variant)); } QNetworkAccessManager *QV8Engine::networkAccessManager() @@ -490,22 +343,9 @@ const QStringHash<bool> &QV8Engine::illegalNames() const return m_illegalNames; } -// Requires a handle scope -v8::Local<v8::Array> QV8Engine::getOwnPropertyNames(v8::Handle<v8::Object> o) -{ - // FIXME Newer v8 have API for this function - v8::TryCatch tc; - v8::Handle<v8::Value> args[] = { o }; - v8::Local<v8::Value> r = m_getOwnPropertyNames->Call(global(), 1, args); - if (tc.HasCaught()) - return v8::Array::New(); - else - return v8::Local<v8::Array>::Cast(r); -} - QQmlContextData *QV8Engine::callingContext() { - return m_contextWrapper.callingContext(); + return QV4::QmlContextWrapper::callingContext(m_v4Engine); } // Converts a JS value to a QVariant. @@ -517,178 +357,58 @@ QQmlContextData *QV8Engine::callingContext() // Date -> QVariant(QDateTime) // RegExp -> QVariant(QRegExp) // [Any other object] -> QVariantMap(...) -QVariant QV8Engine::toBasicVariant(v8::Handle<v8::Value> value) +QVariant QV8Engine::toBasicVariant(const QV4::Value &value) { - if (value->IsNull() || value->IsUndefined()) + if (value.isNull() || value.isUndefined()) return QVariant(); - if (value->IsBoolean()) - return value->ToBoolean()->Value(); - if (value->IsInt32()) - return value->ToInt32()->Value(); - if (value->IsNumber()) - return value->ToNumber()->Value(); - if (value->IsString()) - return m_stringWrapper.toString(value->ToString()); - if (value->IsDate()) - return qtDateTimeFromJsDate(v8::Handle<v8::Date>::Cast(value)->NumberValue()); + if (value.isBoolean()) + return value.booleanValue(); + if (value.isInteger()) + return value.integerValue(); + if (value.isNumber()) + return value.asDouble(); + if (value.isString()) + return value.stringValue()->toQString(); + if (QV4::DateObject *d = value.asDateObject()) + return d->toQDateTime(); // NOTE: since we convert QTime to JS Date, round trip will change the variant type (to QDateTime)! - Q_ASSERT(value->IsObject()); + Q_ASSERT(value.isObject()); - if (value->IsRegExp()) { - v8::Context::Scope scope(context()); - return QJSConverter::toRegExp(v8::Handle<v8::RegExp>::Cast(value)); - } - if (value->IsArray()) { - v8::Context::Scope scope(context()); + if (QV4::RegExpObject *re = value.as<QV4::RegExpObject>()) + return re->toQRegExp(); + if (QV4::ArrayObject *a = value.asArrayObject()) { QVariantList rv; - v8::Handle<v8::Array> array = v8::Handle<v8::Array>::Cast(value); - int length = array->Length(); + int length = a->arrayLength(); for (int ii = 0; ii < length; ++ii) - rv << toVariant(array->Get(ii), -1); + rv << toVariant(a->getIndexed(ii), -1); return rv; } - if (!value->IsFunction()) { - v8::Context::Scope scope(context()); - v8::Handle<v8::Object> object = value->ToObject(); - return variantMapFromJS(object); - } + if (!value.asFunctionObject()) + return variantMapFromJS(value.asObject()); return QVariant(); } -struct StaticQtMetaObject : public QObject +void QV8Engine::initializeGlobal() { - static const QMetaObject *get() - { return &staticQtMetaObject; } -}; + QV4::GlobalExtensions::init(m_engine, m_v4Engine->globalObject); -void QV8Engine::initializeGlobal(v8::Handle<v8::Object> global) -{ - using namespace QQmlBuiltinFunctions; - - v8::Local<v8::Object> console = v8::Object::New(); - v8::Local<v8::Function> consoleLogFn = V8FUNCTION(consoleLog, this); - - console->Set(v8::String::New("debug"), consoleLogFn); - console->Set(v8::String::New("log"), consoleLogFn); - console->Set(v8::String::New("info"), consoleLogFn); - console->Set(v8::String::New("warn"), V8FUNCTION(consoleWarn, this)); - console->Set(v8::String::New("error"), V8FUNCTION(consoleError, this)); - console->Set(v8::String::New("assert"), V8FUNCTION(consoleAssert, this)); - - console->Set(v8::String::New("count"), V8FUNCTION(consoleCount, this)); - console->Set(v8::String::New("profile"), V8FUNCTION(consoleProfile, this)); - console->Set(v8::String::New("profileEnd"), V8FUNCTION(consoleProfileEnd, this)); - console->Set(v8::String::New("time"), V8FUNCTION(consoleTime, this)); - console->Set(v8::String::New("timeEnd"), V8FUNCTION(consoleTimeEnd, this)); - console->Set(v8::String::New("trace"), V8FUNCTION(consoleTrace, this)); - console->Set(v8::String::New("exception"), V8FUNCTION(consoleException, this)); - - v8::Local<v8::Object> qt = v8::Object::New(); - - // Set all the enums from the "Qt" namespace - const QMetaObject *qtMetaObject = StaticQtMetaObject::get(); - for (int ii = 0; ii < qtMetaObject->enumeratorCount(); ++ii) { - QMetaEnum enumerator = qtMetaObject->enumerator(ii); - for (int jj = 0; jj < enumerator.keyCount(); ++jj) { - qt->Set(v8::String::New(enumerator.key(jj)), v8::Integer::New(enumerator.value(jj))); - } - } - qt->Set(v8::String::New("Asynchronous"), v8::Integer::New(0)); - qt->Set(v8::String::New("Synchronous"), v8::Integer::New(1)); - - qt->Set(v8::String::New("include"), V8FUNCTION(QV8Include::include, this)); - qt->Set(v8::String::New("isQtObject"), V8FUNCTION(isQtObject, this)); - qt->Set(v8::String::New("rgba"), V8FUNCTION(rgba, this)); - qt->Set(v8::String::New("hsla"), V8FUNCTION(hsla, this)); - qt->Set(v8::String::New("colorEqual"), V8FUNCTION(colorEqual, this)); - qt->Set(v8::String::New("font"), V8FUNCTION(font, this)); - qt->Set(v8::String::New("rect"), V8FUNCTION(rect, this)); - qt->Set(v8::String::New("point"), V8FUNCTION(point, this)); - qt->Set(v8::String::New("size"), V8FUNCTION(size, this)); - - qt->Set(v8::String::New("vector2d"), V8FUNCTION(vector2d, this)); - qt->Set(v8::String::New("vector3d"), V8FUNCTION(vector3d, this)); - qt->Set(v8::String::New("vector4d"), V8FUNCTION(vector4d, this)); - qt->Set(v8::String::New("quaternion"), V8FUNCTION(quaternion, this)); - qt->Set(v8::String::New("matrix4x4"), V8FUNCTION(matrix4x4, this)); - - qt->Set(v8::String::New("formatDate"), V8FUNCTION(formatDate, this)); - qt->Set(v8::String::New("formatTime"), V8FUNCTION(formatTime, this)); - qt->Set(v8::String::New("formatDateTime"), V8FUNCTION(formatDateTime, this)); - - qt->Set(v8::String::New("openUrlExternally"), V8FUNCTION(openUrlExternally, this)); - qt->Set(v8::String::New("fontFamilies"), V8FUNCTION(fontFamilies, this)); - qt->Set(v8::String::New("md5"), V8FUNCTION(md5, this)); - qt->Set(v8::String::New("btoa"), V8FUNCTION(btoa, this)); - qt->Set(v8::String::New("atob"), V8FUNCTION(atob, this)); - qt->Set(v8::String::New("resolvedUrl"), V8FUNCTION(resolvedUrl, this)); - qt->Set(v8::String::New("locale"), V8FUNCTION(locale, this)); - qt->Set(v8::String::New("binding"), V8FUNCTION(binding, this)); - - if (m_engine) { - qt->SetAccessor(v8::String::New("platform"), getPlatform, 0, v8::External::New(this)); - qt->SetAccessor(v8::String::New("application"), getApplication, 0, v8::External::New(this)); -#ifndef QT_NO_IM - qt->SetAccessor(v8::String::New("inputMethod"), getInputMethod, 0, v8::External::New(this)); -#endif - qt->Set(v8::String::New("lighter"), V8FUNCTION(lighter, this)); - qt->Set(v8::String::New("darker"), V8FUNCTION(darker, this)); - qt->Set(v8::String::New("tint"), V8FUNCTION(tint, this)); - qt->Set(v8::String::New("quit"), V8FUNCTION(quit, this)); - qt->Set(v8::String::New("createQmlObject"), V8FUNCTION(createQmlObject, this)); - qt->Set(v8::String::New("createComponent"), V8FUNCTION(createComponent, this)); - } - -#ifndef QT_NO_TRANSLATION - global->Set(v8::String::New("qsTranslate"), V8FUNCTION(qsTranslate, this)); - global->Set(v8::String::New("QT_TRANSLATE_NOOP"), V8FUNCTION(qsTranslateNoOp, this)); - global->Set(v8::String::New("qsTr"), V8FUNCTION(qsTr, this)); - global->Set(v8::String::New("QT_TR_NOOP"), V8FUNCTION(qsTrNoOp, this)); - global->Set(v8::String::New("qsTrId"), V8FUNCTION(qsTrId, this)); - global->Set(v8::String::New("QT_TRID_NOOP"), V8FUNCTION(qsTrIdNoOp, this)); -#endif + QQmlLocale::registerStringLocaleCompare(m_v4Engine); + QQmlDateExtension::registerExtension(m_v4Engine); + QQmlNumberExtension::registerExtension(m_v4Engine); - global->Set(v8::String::New("print"), consoleLogFn); - global->Set(v8::String::New("console"), console); - global->Set(v8::String::New("Qt"), qt); - global->Set(v8::String::New("gc"), V8FUNCTION(QQmlBuiltinFunctions::gc, this)); - - { -#define STRING_ARG "(function(stringArg) { "\ - " String.prototype.arg = (function() {"\ - " return stringArg.apply(this, arguments);"\ - " })"\ - "})" - - v8::Local<v8::Script> registerArg = v8::Script::New(v8::String::New(STRING_ARG), 0, 0, v8::Handle<v8::String>(), v8::Script::NativeMode); - v8::Local<v8::Value> result = registerArg->Run(); - Q_ASSERT(result->IsFunction()); - v8::Local<v8::Function> registerArgFunc = v8::Local<v8::Function>::Cast(result); - v8::Handle<v8::Value> args = V8FUNCTION(stringArg, this); - registerArgFunc->Call(v8::Local<v8::Object>::Cast(registerArgFunc), 1, &args); -#undef STRING_ARG - } - - QQmlLocale::registerStringLocaleCompare(this); - QQmlDateExtension::registerExtension(this); - QQmlNumberExtension::registerExtension(this); - - qt_add_domexceptions(this); + qt_add_domexceptions(m_v4Engine); m_xmlHttpRequestData = qt_add_qmlxmlhttprequest(this); - qt_add_sqlexceptions(this); + qt_add_sqlexceptions(m_v4Engine); { - v8::Handle<v8::Value> args[] = { global }; - v8::Local<v8::Value> names = m_getOwnPropertyNames->Call(global, 1, args); - v8::Local<v8::Array> namesArray = v8::Local<v8::Array>::Cast(names); - for (quint32 ii = 0; ii < namesArray->Length(); ++ii) - m_illegalNames.insert(toString(namesArray->Get(ii)), true); + for (uint i = 0; i < m_v4Engine->globalObject->internalClass->size; ++i) + m_illegalNames.insert(m_v4Engine->globalObject->internalClass->nameMap.at(i)->toQString(), true); } { @@ -710,63 +430,24 @@ void QV8Engine::initializeGlobal(v8::Handle<v8::Object> global) " }"\ "})" - v8::Local<v8::Script> freeze = v8::Script::New(v8::String::New(FREEZE_SOURCE)); - v8::Local<v8::Value> result = freeze->Run(); - Q_ASSERT(result->IsFunction()); - m_freezeObject = qPersistentNew(v8::Local<v8::Function>::Cast(result)); + QV4::Value result = QV4::Script::evaluate(m_v4Engine, QString::fromUtf8(FREEZE_SOURCE), 0); + Q_ASSERT(result.asFunctionObject()); + m_freezeObject = result; #undef FREEZE_SOURCE } } -void QV8Engine::freezeObject(v8::Handle<v8::Value> value) +void QV8Engine::freezeObject(const QV4::Value &value) { - v8::Handle<v8::Value> args[] = { value }; - m_freezeObject->Call(global(), 1, args); + QV4::Value args = value; + m_freezeObject.value().asFunctionObject()->call(QV4::Value::fromObject(m_v4Engine->globalObject), &args, 1); } void QV8Engine::gc() { - v8::V8::LowMemoryNotification(); - while (!v8::V8::IdleNotification()) {} -} - -#ifdef QML_GLOBAL_HANDLE_DEBUGGING -#include <QtCore/qthreadstorage.h> -static QThreadStorage<QSet<void *> *> QV8Engine_activeHandles; - -void QV8Engine::registerHandle(void *handle) -{ - if (!handle) { - qWarning("Attempting to register a null handle"); - return; - } - - if (!QV8Engine_activeHandles.hasLocalData()) - QV8Engine_activeHandles.setLocalData(new QSet<void *>); - - if (QV8Engine_activeHandles.localData()->contains(handle)) { - qFatal("Handle %p already alive", handle); - } else { - QV8Engine_activeHandles.localData()->insert(handle); - } + m_v4Engine->memoryManager->runGC(); } -void QV8Engine::releaseHandle(void *handle) -{ - if (!handle) - return; - - if (!QV8Engine_activeHandles.hasLocalData()) - QV8Engine_activeHandles.setLocalData(new QSet<void *>); - - if (QV8Engine_activeHandles.localData()->contains(handle)) { - QV8Engine_activeHandles.localData()->remove(handle); - } else { - qFatal("Handle %p already dead", handle); - } -} -#endif - struct QV8EngineRegistrationData { QV8EngineRegistrationData() : extensionCount(0) {} @@ -797,115 +478,10 @@ void QV8Engine::setExtensionData(int index, Deletable *data) m_extensionData[index] = data; } -double QV8Engine::qtDateTimeToJsDate(const QDateTime &dt) -{ - if (!dt.isValid()) { - return qSNaN(); - } - - return dt.toMSecsSinceEpoch(); -} - -QDateTime QV8Engine::qtDateTimeFromJsDate(double jsDate) -{ - if (qIsNaN(jsDate)) - return QDateTime(); - - return QDateTime::fromMSecsSinceEpoch(jsDate); -} - -v8::Persistent<v8::Object> *QV8Engine::findOwnerAndStrength(QObject *object, bool *shouldBeStrong) -{ - QQmlData *data = QQmlData::get(object); - if (data && data->rootObjectInCreation) { // When the object is still being created it may not show up to the GC. - *shouldBeStrong = true; - return 0; - } - - QObject *parent = object->parent(); - if (!parent) { - // if the object has JS ownership, the object's v8object owns the lifetime of the persistent value. - if (QQmlEngine::objectOwnership(object) == QQmlEngine::JavaScriptOwnership) { - *shouldBeStrong = false; - return &(QQmlData::get(object)->v8object); - } - - // no parent, and has CPP ownership - doesn't have an implicit parent. - *shouldBeStrong = true; - return 0; - } - - // if it is owned by CPP, it's root parent may still be owned by JS. - // in that case, the owner of the persistent handle is the root parent's v8object. - while (parent->parent()) - parent = parent->parent(); - - if (QQmlEngine::objectOwnership(parent) == QQmlEngine::JavaScriptOwnership) { - // root parent is owned by JS. It's v8object owns the persistent value in question. - *shouldBeStrong = false; - return &(QQmlData::get(parent)->v8object); - } else { - // root parent has CPP ownership. The persistent value should not be made weak. - *shouldBeStrong = true; - return 0; - } -} - -void QV8Engine::addRelationshipForGC(QObject *object, v8::Persistent<v8::Value> handle) -{ - if (!object || handle.IsEmpty()) - return; - - bool handleShouldBeStrong = false; - v8::Persistent<v8::Object> *implicitOwner = findOwnerAndStrength(object, &handleShouldBeStrong); - if (handleShouldBeStrong) { - v8::V8::AddImplicitReferences(m_strongReferencer, &handle, 1); - } else if (!implicitOwner->IsEmpty()) { - v8::V8::AddImplicitReferences(*implicitOwner, &handle, 1); - } -} - -void QV8Engine::addRelationshipForGC(QObject *object, QObject *other) -{ - if (!object || !other) - return; - - bool handleShouldBeStrong = false; - v8::Persistent<v8::Object> *implicitOwner = findOwnerAndStrength(object, &handleShouldBeStrong); - v8::Persistent<v8::Value> handle = QQmlData::get(other, true)->v8object; - if (handle.IsEmpty()) // no JS data to keep alive. - return; - else if (handleShouldBeStrong) - v8::V8::AddImplicitReferences(m_strongReferencer, &handle, 1); - else if (!implicitOwner->IsEmpty()) - v8::V8::AddImplicitReferences(*implicitOwner, &handle, 1); -} - -static QThreadStorage<QV8Engine::ThreadData*> perThreadEngineData; - -bool QV8Engine::hasThreadData() -{ - return perThreadEngineData.hasLocalData(); -} - -QV8Engine::ThreadData *QV8Engine::threadData() -{ - Q_ASSERT(perThreadEngineData.hasLocalData()); - return perThreadEngineData.localData(); -} - -void QV8Engine::ensurePerThreadIsolate() -{ - if (!perThreadEngineData.hasLocalData()) - perThreadEngineData.setLocalData(new ThreadData); -} - void QV8Engine::initQmlGlobalObject() { - v8::HandleScope handels; - v8::Context::Scope contextScope(m_context); - initializeGlobal(m_context->Global()); - freezeObject(m_context->Global()); + initializeGlobal(); + freezeObject(QV4::Value::fromObject(m_v4Engine->globalObject)); } void QV8Engine::setEngine(QQmlEngine *engine) @@ -914,40 +490,51 @@ void QV8Engine::setEngine(QQmlEngine *engine) initQmlGlobalObject(); } -v8::Handle<v8::Value> QV8Engine::throwException(v8::Handle<v8::Value> value) +QV4::Value QV8Engine::global() { - v8::ThrowException(value); - return value; + return QV4::Value::fromObject(m_v4Engine->globalObject); } // Converts a QVariantList to JS. // The result is a new Array object with length equal to the length // of the QVariantList, and the elements being the QVariantList's // elements converted to JS, recursively. -v8::Local<v8::Array> QV8Engine::variantListToJS(const QVariantList &lst) +QV4::Value QV8Engine::variantListToJS(const QVariantList &lst) { - v8::Local<v8::Array> result = v8::Array::New(lst.size()); - for (int i = 0; i < lst.size(); ++i) - result->Set(i, variantToJS(lst.at(i))); - return result; + QV4::ArrayObject *a = m_v4Engine->newArrayObject(); + a->arrayReserve(lst.size()); + for (int i = 0; i < lst.size(); i++) + a->arrayData[i].value = variantToJS(lst.at(i)); + a->arrayDataLen = lst.size(); + a->setArrayLengthUnchecked(lst.size()); + return QV4::Value::fromObject(a); } // Converts a JS Array object to a QVariantList. // The result is a QVariantList with length equal to the length // of the JS Array, and elements being the JS Array's elements // converted to QVariants, recursively. -QVariantList QV8Engine::variantListFromJS(v8::Handle<v8::Array> jsArray, +QVariantList QV8Engine::variantListFromJS(QV4::ArrayObject *a, V8ObjectSet &visitedObjects) { QVariantList result; - if (visitedObjects.contains(jsArray)) - return result; // Avoid recursion. - v8::HandleScope handleScope; - visitedObjects.insert(jsArray); - uint32_t length = jsArray->Length(); - for (uint32_t i = 0; i < length; ++i) - result.append(variantFromJS(jsArray->Get(i), visitedObjects)); - visitedObjects.remove(jsArray); + if (!a) + return result; + + if (visitedObjects.contains(a)) + // Avoid recursion. + return result; + + visitedObjects.insert(a); + + quint32 length = a->arrayLength(); + for (quint32 i = 0; i < length; ++i) { + QV4::Value v = a->getIndexed(i); + result.append(variantFromJS(v, visitedObjects)); + } + + visitedObjects.remove(a); + return result; } @@ -955,91 +542,100 @@ QVariantList QV8Engine::variantListFromJS(v8::Handle<v8::Array> jsArray, // The result is a new Object object with property names being // the keys of the QVariantMap, and values being the values of // the QVariantMap converted to JS, recursively. -v8::Local<v8::Object> QV8Engine::variantMapToJS(const QVariantMap &vmap) +QV4::Value QV8Engine::variantMapToJS(const QVariantMap &vmap) { - v8::Local<v8::Object> result = v8::Object::New(); + QV4::Object *o = m_v4Engine->newObject(); QVariantMap::const_iterator it; - for (it = vmap.constBegin(); it != vmap.constEnd(); ++it) - result->Set(QJSConverter::toString(it.key()), variantToJS(it.value())); - return result; + for (it = vmap.constBegin(); it != vmap.constEnd(); ++it) { + QV4::Property *p = o->insertMember(m_v4Engine->newIdentifier(it.key()), QV4::Attr_Data); + p->value = variantToJS(it.value()); + } + return QV4::Value::fromObject(o); } // Converts a JS Object to a QVariantMap. // The result is a QVariantMap with keys being the property names // of the object, and values being the values of the JS object's // properties converted to QVariants, recursively. -QVariantMap QV8Engine::variantMapFromJS(v8::Handle<v8::Object> jsObject, +QVariantMap QV8Engine::variantMapFromJS(QV4::Object *o, V8ObjectSet &visitedObjects) { QVariantMap result; - v8::HandleScope handleScope; - v8::Handle<v8::Array> propertyNames = jsObject->GetPropertyNames(); - uint32_t length = propertyNames->Length(); - if (length == 0) + if (!o || o->asFunctionObject()) return result; - if (visitedObjects.contains(jsObject)) - return result; // Avoid recursion. + if (visitedObjects.contains(o)) { + // Avoid recursion. + // For compatibility with QVariant{List,Map} conversion, we return an + // empty object (and no error is thrown). + return result; + } + + visitedObjects.insert(o); + + QV4::ObjectIterator it(o, QV4::ObjectIterator::EnumerableOnly); + while (1) { + QV4::Value v; + QV4::Value name = it.nextPropertyNameAsString(&v); + if (name.isNull()) + break; - visitedObjects.insert(jsObject); - // TODO: Only object's own property names. Include non-enumerable properties. - for (uint32_t i = 0; i < length; ++i) { - v8::Handle<v8::Value> name = propertyNames->Get(i); - result.insert(QJSConverter::toString(name->ToString()), - variantFromJS(jsObject->Get(name), visitedObjects)); + QString key = name.toQString(); + result.insert(key, variantFromJS(v, visitedObjects)); } - visitedObjects.remove(jsObject); + + visitedObjects.remove(o); return result; } // Converts the meta-type defined by the given type and data to JS. // Returns the value if conversion succeeded, an empty handle otherwise. -v8::Handle<v8::Value> QV8Engine::metaTypeToJS(int type, const void *data) +QV4::Value QV8Engine::metaTypeToJS(int type, const void *data) { Q_ASSERT(data != 0); - v8::Handle<v8::Value> result; + QV4::Value result; // check if it's one of the types we know switch (QMetaType::Type(type)) { case QMetaType::UnknownType: case QMetaType::Void: - return v8::Undefined(); + return QV4::Value::undefinedValue(); case QMetaType::Bool: - return v8::Boolean::New(*reinterpret_cast<const bool*>(data)); + return QV4::Value::fromBoolean(*reinterpret_cast<const bool*>(data)); case QMetaType::Int: - return v8::Int32::New(*reinterpret_cast<const int*>(data)); + return QV4::Value::fromInt32(*reinterpret_cast<const int*>(data)); case QMetaType::UInt: - return v8::Uint32::New(*reinterpret_cast<const uint*>(data)); + return QV4::Value::fromUInt32(*reinterpret_cast<const uint*>(data)); case QMetaType::LongLong: - return v8::Number::New(double(*reinterpret_cast<const qlonglong*>(data))); + return QV4::Value::fromDouble(double(*reinterpret_cast<const qlonglong*>(data))); 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 v8::Number::New(double((qlonglong)*reinterpret_cast<const qulonglong*>(data))); + return QV4::Value::fromDouble(double((qlonglong)*reinterpret_cast<const qulonglong*>(data))); #elif defined(Q_CC_MSVC) && !defined(Q_CC_MSVC_NET) - return v8::Number::New(double((qlonglong)*reinterpret_cast<const qulonglong*>(data))); + return QV4::Value::fromDouble(double((qlonglong)*reinterpret_cast<const qulonglong*>(data))); #else - return v8::Number::New(double(*reinterpret_cast<const qulonglong*>(data))); + return QV4::Value::fromDouble(double(*reinterpret_cast<const qulonglong*>(data))); #endif case QMetaType::Double: - return v8::Number::New(double(*reinterpret_cast<const double*>(data))); + return QV4::Value::fromDouble(*reinterpret_cast<const double*>(data)); case QMetaType::QString: - return QJSConverter::toString(*reinterpret_cast<const QString*>(data)); + return QV4::Value::fromString(m_v4Engine->current, *reinterpret_cast<const QString*>(data)); case QMetaType::Float: - return v8::Number::New(*reinterpret_cast<const float*>(data)); + return QV4::Value::fromDouble(*reinterpret_cast<const float*>(data)); case QMetaType::Short: - return v8::Int32::New(*reinterpret_cast<const short*>(data)); + return QV4::Value::fromInt32(*reinterpret_cast<const short*>(data)); case QMetaType::UShort: - return v8::Uint32::New(*reinterpret_cast<const unsigned short*>(data)); + return QV4::Value::fromUInt32(*reinterpret_cast<const unsigned short*>(data)); case QMetaType::Char: - return v8::Int32::New(*reinterpret_cast<const char*>(data)); + return QV4::Value::fromInt32(*reinterpret_cast<const char*>(data)); case QMetaType::UChar: - return v8::Uint32::New(*reinterpret_cast<const unsigned char*>(data)); + return QV4::Value::fromUInt32(*reinterpret_cast<const unsigned char*>(data)); case QMetaType::QChar: - return v8::Uint32::New((*reinterpret_cast<const QChar*>(data)).unicode()); + return QV4::Value::fromUInt32((*reinterpret_cast<const QChar*>(data)).unicode()); case QMetaType::QStringList: - result = QJSConverter::toStringList(*reinterpret_cast<const QStringList *>(data)); + result = QV4::Value::fromObject(m_v4Engine->newArrayObject(*reinterpret_cast<const QStringList *>(data))); break; case QMetaType::QVariantList: result = variantListToJS(*reinterpret_cast<const QVariantList *>(data)); @@ -1048,39 +644,39 @@ v8::Handle<v8::Value> QV8Engine::metaTypeToJS(int type, const void *data) result = variantMapToJS(*reinterpret_cast<const QVariantMap *>(data)); break; case QMetaType::QDateTime: - result = QJSConverter::toDateTime(*reinterpret_cast<const QDateTime *>(data)); + result = QV4::Value::fromObject(m_v4Engine->newDateObject(*reinterpret_cast<const QDateTime *>(data))); break; case QMetaType::QDate: - result = QJSConverter::toDateTime(QDateTime(*reinterpret_cast<const QDate *>(data))); + result = QV4::Value::fromObject(m_v4Engine->newDateObject(QDateTime(*reinterpret_cast<const QDate *>(data)))); break; case QMetaType::QRegExp: - result = QJSConverter::toRegExp(*reinterpret_cast<const QRegExp *>(data)); + result = QV4::Value::fromObject(m_v4Engine->newRegExpObject(*reinterpret_cast<const QRegExp *>(data))); break; case QMetaType::QObjectStar: - result = newQObject(*reinterpret_cast<QObject* const *>(data)); + result = QV4::QObjectWrapper::wrap(m_v4Engine, *reinterpret_cast<QObject* const *>(data)); break; case QMetaType::QVariant: result = variantToJS(*reinterpret_cast<const QVariant*>(data)); break; case QMetaType::QJsonValue: - result = jsonValueToJS(*reinterpret_cast<const QJsonValue *>(data)); + result = QV4::JsonObject::fromJsonValue(m_v4Engine, *reinterpret_cast<const QJsonValue *>(data)); break; case QMetaType::QJsonObject: - result = jsonObjectToJS(*reinterpret_cast<const QJsonObject *>(data)); + result = QV4::JsonObject::fromJsonObject(m_v4Engine, *reinterpret_cast<const QJsonObject *>(data)); break; case QMetaType::QJsonArray: - result = jsonArrayToJS(*reinterpret_cast<const QJsonArray *>(data)); + result = QV4::JsonObject::fromJsonArray(m_v4Engine, *reinterpret_cast<const QJsonArray *>(data)); break; default: if (type == qMetaTypeId<QJSValue>()) { - return QJSValuePrivate::get(*reinterpret_cast<const QJSValue*>(data))->asV8Value(this); + return QJSValuePrivate::get(*reinterpret_cast<const QJSValue*>(data))->getValue(m_v4Engine); } else { QByteArray typeName = QMetaType::typeName(type); if (typeName.endsWith('*') && !*reinterpret_cast<void* const *>(data)) { - return v8::Null(); + return QV4::Value::nullValue(); } else { // Fall back to wrapping in a QVariant. - result = newVariant(QVariant(type, data)); + result = QV4::Value::fromObject(m_v4Engine->newVariantObject(QVariant(type, data))); } } } @@ -1090,102 +686,104 @@ v8::Handle<v8::Value> QV8Engine::metaTypeToJS(int type, const void *data) // Converts a JS value to a meta-type. // data must point to a place that can store a value of the given type. // Returns true if conversion succeeded, false otherwise. -bool QV8Engine::metaTypeFromJS(v8::Handle<v8::Value> value, int type, void *data) { +bool QV8Engine::metaTypeFromJS(const QV4::Value &value, int type, void *data) { // check if it's one of the types we know switch (QMetaType::Type(type)) { case QMetaType::Bool: - *reinterpret_cast<bool*>(data) = value->ToBoolean()->Value(); + *reinterpret_cast<bool*>(data) = value.toBoolean(); return true; case QMetaType::Int: - *reinterpret_cast<int*>(data) = value->ToInt32()->Value(); + *reinterpret_cast<int*>(data) = value.toInt32(); return true; case QMetaType::UInt: - *reinterpret_cast<uint*>(data) = value->ToUint32()->Value(); + *reinterpret_cast<uint*>(data) = value.toUInt32(); return true; case QMetaType::LongLong: - *reinterpret_cast<qlonglong*>(data) = qlonglong(value->ToInteger()->Value()); + *reinterpret_cast<qlonglong*>(data) = qlonglong(value.toInteger()); return true; case QMetaType::ULongLong: - *reinterpret_cast<qulonglong*>(data) = qulonglong(value->ToInteger()->Value()); + *reinterpret_cast<qulonglong*>(data) = qulonglong(value.toInteger()); return true; case QMetaType::Double: - *reinterpret_cast<double*>(data) = value->ToNumber()->Value(); + *reinterpret_cast<double*>(data) = value.toNumber(); return true; case QMetaType::QString: - if (value->IsUndefined() || value->IsNull()) + if (value.isUndefined() || value.isNull()) *reinterpret_cast<QString*>(data) = QString(); else - *reinterpret_cast<QString*>(data) = QJSConverter::toString(value->ToString()); + *reinterpret_cast<QString*>(data) = value.toString(m_v4Engine->current)->toQString(); return true; case QMetaType::Float: - *reinterpret_cast<float*>(data) = value->ToNumber()->Value(); + *reinterpret_cast<float*>(data) = value.toNumber(); return true; case QMetaType::Short: - *reinterpret_cast<short*>(data) = short(value->ToInt32()->Value()); + *reinterpret_cast<short*>(data) = short(value.toInt32()); return true; case QMetaType::UShort: - *reinterpret_cast<unsigned short*>(data) = ushort(value->ToInt32()->Value()); // ### QScript::ToUInt16() + *reinterpret_cast<unsigned short*>(data) = value.toUInt16(); return true; case QMetaType::Char: - *reinterpret_cast<char*>(data) = char(value->ToInt32()->Value()); + *reinterpret_cast<char*>(data) = char(value.toInt32()); return true; case QMetaType::UChar: - *reinterpret_cast<unsigned char*>(data) = (unsigned char)(value->ToInt32()->Value()); + *reinterpret_cast<unsigned char*>(data) = (unsigned char)(value.toInt32()); return true; case QMetaType::QChar: - if (value->IsString()) { - QString str = QJSConverter::toString(v8::Handle<v8::String>::Cast(value)); + if (value.isString()) { + QString str = value.stringValue()->toQString(); *reinterpret_cast<QChar*>(data) = str.isEmpty() ? QChar() : str.at(0); } else { - *reinterpret_cast<QChar*>(data) = QChar(ushort(value->ToInt32()->Value())); // ### QScript::ToUInt16() + *reinterpret_cast<QChar*>(data) = QChar(ushort(value.toUInt16())); } return true; case QMetaType::QDateTime: - if (value->IsDate()) { - *reinterpret_cast<QDateTime *>(data) = QJSConverter::toDateTime(v8::Handle<v8::Date>::Cast(value)); + if (QV4::DateObject *d = value.asDateObject()) { + *reinterpret_cast<QDateTime *>(data) = d->toQDateTime(); return true; } break; case QMetaType::QDate: - if (value->IsDate()) { - *reinterpret_cast<QDate *>(data) = QJSConverter::toDateTime(v8::Handle<v8::Date>::Cast(value)).date(); + if (QV4::DateObject *d = value.asDateObject()) { + *reinterpret_cast<QDate *>(data) = d->toQDateTime().date(); return true; } break; case QMetaType::QRegExp: - if (value->IsRegExp()) { - *reinterpret_cast<QRegExp *>(data) = QJSConverter::toRegExp(v8::Handle<v8::RegExp>::Cast(value)); + if (QV4::RegExpObject *r = value.as<QV4::RegExpObject>()) { + *reinterpret_cast<QRegExp *>(data) = r->toQRegExp(); return true; } break; - case QMetaType::QObjectStar: - if (isQObject(value) || value->IsNull()) { + case QMetaType::QObjectStar: { + QV4::QObjectWrapper *qobjectWrapper = value.as<QV4::QObjectWrapper>(); + if (qobjectWrapper || value.isNull()) { *reinterpret_cast<QObject* *>(data) = qtObjectFromJS(value); return true; } break; + } case QMetaType::QStringList: - if (value->IsArray()) { - *reinterpret_cast<QStringList *>(data) = QJSConverter::toStringList(v8::Handle<v8::Array>::Cast(value)); + if (QV4::ArrayObject *a = value.asArrayObject()) { + *reinterpret_cast<QStringList *>(data) = a->toQStringList(); return true; } break; case QMetaType::QVariantList: - if (value->IsArray()) { - *reinterpret_cast<QVariantList *>(data) = variantListFromJS(v8::Handle<v8::Array>::Cast(value)); + if (QV4::ArrayObject *a = value.asArrayObject()) { + *reinterpret_cast<QVariantList *>(data) = variantListFromJS(a); return true; } break; case QMetaType::QVariantMap: - if (value->IsObject()) { - *reinterpret_cast<QVariantMap *>(data) = variantMapFromJS(v8::Handle<v8::Object>::Cast(value)); + if (QV4::Object *o = value.asObject()) { + *reinterpret_cast<QVariantMap *>(data) = variantMapFromJS(o); return true; } break; case QMetaType::QVariant: *reinterpret_cast<QVariant*>(data) = variantFromJS(value); return true; case QMetaType::QJsonValue: - *reinterpret_cast<QJsonValue *>(data) = jsonValueFromJS(value); + *reinterpret_cast<QJsonValue *>(data) = QV4::JsonObject::toJsonValue(value); return true; case QMetaType::QJsonObject: - *reinterpret_cast<QJsonObject *>(data) = jsonObjectFromJS(value); + *reinterpret_cast<QJsonObject *>(data) = QV4::JsonObject::toJsonObject(value.asObject()); return true; case QMetaType::QJsonArray: - *reinterpret_cast<QJsonArray *>(data) = jsonArrayFromJS(value); + *reinterpret_cast<QJsonArray *>(data) = QV4::JsonObject::toJsonArray(value.asArrayObject()); return true; default: ; @@ -1215,25 +813,25 @@ bool QV8Engine::metaTypeFromJS(v8::Handle<v8::Value> value, int type, void *data QByteArray name = QMetaType::typeName(type); if (convertToNativeQObject(value, name, reinterpret_cast<void* *>(data))) return true; - if (isVariant(value) && name.endsWith('*')) { + if (value.as<QV4::VariantObject>() && name.endsWith('*')) { int valueType = QMetaType::type(name.left(name.size()-1)); - QVariant &var = variantValue(value); + QVariant &var = value.as<QV4::VariantObject>()->data; if (valueType == var.userType()) { // We have T t, T* is requested, so return &t. *reinterpret_cast<void* *>(data) = var.data(); return true; - } else { + } else if (QV4::Object *o = value.asObject()) { // Look in the prototype chain. - v8::Handle<v8::Value> proto = value->ToObject()->GetPrototype(); - while (proto->IsObject()) { + QV4::Object *proto = o->prototype; + while (proto) { bool canCast = false; - if (isVariant(proto)) { - canCast = (type == variantValue(proto).userType()) - || (valueType && (valueType == variantValue(proto).userType())); + if (QV4::VariantObject *vo = proto->as<QV4::VariantObject>()) { + const QVariant &v = vo->data; + canCast = (type == v.userType()) || (valueType && (valueType == v.userType())); } - else if (isQObject(proto)) { + else if (proto->as<QV4::QObjectWrapper>()) { QByteArray className = name.left(name.size()-1); - if (QObject *qobject = qtObjectFromJS(proto)) + if (QObject *qobject = qtObjectFromJS(QV4::Value::fromObject(proto))) canCast = qobject->qt_metacast(className) != 0; } if (canCast) { @@ -1244,14 +842,14 @@ bool QV8Engine::metaTypeFromJS(v8::Handle<v8::Value> value, int type, void *data *reinterpret_cast<void* *>(data) = var.data(); return true; } - proto = proto->ToObject()->GetPrototype(); + proto = proto->prototype; } } - } else if (value->IsNull() && name.endsWith('*')) { + } else if (value.isNull() && name.endsWith('*')) { *reinterpret_cast<void* *>(data) = 0; return true; } else if (type == qMetaTypeId<QJSValue>()) { - *reinterpret_cast<QJSValue*>(data) = QJSValuePrivate::get(new QJSValuePrivate(this, value)); + *reinterpret_cast<QJSValue*>(data) = QJSValuePrivate::get(new QJSValuePrivate(m_v4Engine, value)); return true; } @@ -1259,7 +857,7 @@ bool QV8Engine::metaTypeFromJS(v8::Handle<v8::Value> value, int type, void *data } // Converts a QVariant to JS. -v8::Handle<v8::Value> QV8Engine::variantToJS(const QVariant &value) +QV4::Value QV8Engine::variantToJS(const QVariant &value) { return metaTypeToJS(value.userType(), value.constData()); } @@ -1274,71 +872,40 @@ v8::Handle<v8::Value> QV8Engine::variantToJS(const QVariant &value) // Date -> QVariant(QDateTime) // RegExp -> QVariant(QRegExp) // [Any other object] -> QVariantMap(...) -QVariant QV8Engine::variantFromJS(v8::Handle<v8::Value> value, +QVariant QV8Engine::variantFromJS(const QV4::Value &value, V8ObjectSet &visitedObjects) { - Q_ASSERT(!value.IsEmpty()); - if (value->IsUndefined()) + Q_ASSERT(!value.isEmpty()); + if (value.isUndefined()) return QVariant(); - if (value->IsNull()) + if (value.isNull()) return QVariant(QMetaType::VoidStar, 0); - if (value->IsBoolean()) - return value->ToBoolean()->Value(); - if (value->IsInt32()) - return value->ToInt32()->Value(); - if (value->IsNumber()) - return value->ToNumber()->Value(); - if (value->IsString()) - return QJSConverter::toString(value->ToString()); - Q_ASSERT(value->IsObject()); - if (value->IsArray()) - return variantListFromJS(v8::Handle<v8::Array>::Cast(value), visitedObjects); - if (value->IsDate()) - return QJSConverter::toDateTime(v8::Handle<v8::Date>::Cast(value)); - if (value->IsRegExp()) - return QJSConverter::toRegExp(v8::Handle<v8::RegExp>::Cast(value)); - if (isVariant(value)) - return variantValue(value); - if (isQObject(value)) + if (value.isBoolean()) + return value.booleanValue(); + if (value.isInteger()) + return value.integerValue(); + if (value.isNumber()) + return value.asDouble(); + if (value.isString()) + return value.stringValue()->toQString(); + Q_ASSERT(value.isObject()); + if (QV4::ArrayObject *a = value.asArrayObject()) + return variantListFromJS(a, visitedObjects); + if (QV4::DateObject *d = value.asDateObject()) + return d->toQDateTime(); + if (QV4::RegExpObject *re = value.as<QV4::RegExpObject>()) + return re->toQRegExp(); + if (QV4::VariantObject *v = value.as<QV4::VariantObject>()) + return v->data; + if (value.as<QV4::QObjectWrapper>()) return qVariantFromValue(qtObjectFromJS(value)); - if (isValueType(value)) - return toValueType(value); - return variantMapFromJS(value->ToObject(), visitedObjects); + if (QV4::QmlValueTypeWrapper *v = value.as<QV4::QmlValueTypeWrapper>()) + return v->toVariant(); + return variantMapFromJS(value.asObject(), visitedObjects); } -v8::Handle<v8::Value> QV8Engine::jsonValueToJS(const QJsonValue &value) -{ - return m_jsonWrapper.fromJsonValue(value); -} -QJsonValue QV8Engine::jsonValueFromJS(v8::Handle<v8::Value> value) -{ - return m_jsonWrapper.toJsonValue(value); -} - -v8::Local<v8::Object> QV8Engine::jsonObjectToJS(const QJsonObject &object) -{ - return m_jsonWrapper.fromJsonObject(object); -} - -QJsonObject QV8Engine::jsonObjectFromJS(v8::Handle<v8::Value> value) -{ - return m_jsonWrapper.toJsonObject(value); -} - -v8::Local<v8::Array> QV8Engine::jsonArrayToJS(const QJsonArray &array) -{ - return m_jsonWrapper.fromJsonArray(array); -} - -QJsonArray QV8Engine::jsonArrayFromJS(v8::Handle<v8::Value> value) -{ - return m_jsonWrapper.toJsonArray(value); -} - -bool QV8Engine::convertToNativeQObject(v8::Handle<v8::Value> value, - const QByteArray &targetType, - void **result) +bool QV8Engine::convertToNativeQObject(const QV4::Value &value, const QByteArray &targetType, void **result) { if (!targetType.endsWith('*')) return false; @@ -1353,73 +920,22 @@ bool QV8Engine::convertToNativeQObject(v8::Handle<v8::Value> value, return false; } -QObject *QV8Engine::qtObjectFromJS(v8::Handle<v8::Value> value) +QObject *QV8Engine::qtObjectFromJS(const QV4::Value &value) { - if (!value->IsObject()) + if (!value.isObject()) return 0; - QV8ObjectResource *r = (QV8ObjectResource *)value->ToObject()->GetExternalResource(); - if (!r) - return 0; - QV8ObjectResource::ResourceType type = r->resourceType(); - if (type == QV8ObjectResource::QObjectType) - return qobjectWrapper()->toQObject(r); - else if (type == QV8ObjectResource::VariantType) { - QVariant variant = variantWrapper()->toVariant(r); + + if (QV4::VariantObject *v = value.as<QV4::VariantObject>()) { + QVariant variant = v->data; int type = variant.userType(); if (type == QMetaType::QObjectStar) return *reinterpret_cast<QObject* const *>(variant.constData()); } - return 0; -} - - -QVariant &QV8Engine::variantValue(v8::Handle<v8::Value> value) -{ - return variantWrapper()->variantValue(value); -} - -// Creates a QVariant wrapper object. -v8::Local<v8::Object> QV8Engine::newVariant(const QVariant &value) -{ - return variantWrapper()->newVariant(value); -} - -QScriptPassPointer<QJSValuePrivate> QV8Engine::evaluate(v8::Handle<v8::Script> script, v8::TryCatch& tryCatch) -{ - v8::HandleScope handleScope; - - if (script.IsEmpty()) { - v8::Handle<v8::Value> exception = tryCatch.Exception(); - if (exception.IsEmpty()) { - // This is possible on syntax errors like { a:12, b:21 } <- missing "(", ")" around expression. - return new QJSValuePrivate(this); - } - return new QJSValuePrivate(this, exception); - } - v8::Handle<v8::Value> result; - result = script->Run(); - if (result.IsEmpty()) { - v8::Handle<v8::Value> exception = tryCatch.Exception(); - // TODO: figure out why v8 doesn't always produce an exception value - //Q_ASSERT(!exception.IsEmpty()); - if (exception.IsEmpty()) - exception = v8::Exception::Error(v8::String::New("missing exception value")); - return new QJSValuePrivate(this, exception); - } - return new QJSValuePrivate(this, result); -} - -QJSValue QV8Engine::scriptValueFromInternal(v8::Handle<v8::Value> value) const -{ - if (value.IsEmpty()) - return QJSValuePrivate::get(new QJSValuePrivate(const_cast<QV8Engine*>(this))); - return QJSValuePrivate::get(new QJSValuePrivate(const_cast<QV8Engine*>(this), value)); -} - -QScriptPassPointer<QJSValuePrivate> QV8Engine::newArray(uint length) -{ - return new QJSValuePrivate(this, v8::Array::New(length)); + QV4::QObjectWrapper *wrapper = value.as<QV4::QObjectWrapper>(); + if (!wrapper) + return 0; + return wrapper->object(); } void QV8Engine::startTimer(const QString &timerName) @@ -1449,107 +965,9 @@ int QV8Engine::consoleCountHelper(const QString &file, quint16 line, quint16 col return number; } -v8::Handle<v8::Value> QV8Engine::getPlatform(v8::Local<v8::String>, const v8::AccessorInfo &info) -{ - QV8Engine *engine = reinterpret_cast<QV8Engine*>(v8::External::Cast(*info.Data())->Value()); - if (!engine->m_platform) { - // Only allocate a platform object once - engine->m_platform = new QQmlPlatform(engine->m_engine); - } - return engine->newQObject(engine->m_platform); -} - -v8::Handle<v8::Value> QV8Engine::getApplication(v8::Local<v8::String>, const v8::AccessorInfo &info) +QV4::Value QV8Engine::toString(const QString &string) { - QV8Engine *engine = reinterpret_cast<QV8Engine*>(v8::External::Cast(*info.Data())->Value()); - if (!engine->m_application) { - // Only allocate an application object once - engine->m_application = QQml_guiProvider()->application(engine->m_engine); - } - return engine->newQObject(engine->m_application); -} - -#ifndef QT_NO_IM -v8::Handle<v8::Value> QV8Engine::getInputMethod(v8::Local<v8::String>, const v8::AccessorInfo &info) -{ - QV8Engine *engine = reinterpret_cast<QV8Engine*>(v8::External::Cast(*info.Data())->Value()); - return engine->newQObject(QQml_guiProvider()->inputMethod(), CppOwnership); -} -#endif - -void QV8GCCallback::registerGcPrologueCallback() -{ - QV8Engine::ThreadData *td = QV8Engine::threadData(); - if (!td->gcPrologueCallbackRegistered) { - td->gcPrologueCallbackRegistered = true; - v8::V8::AddGCPrologueCallback(QV8GCCallback::garbageCollectorPrologueCallback, v8::kGCTypeMarkSweepCompact); - } -} - -QV8GCCallback::Node::Node(PrologueCallback callback) - : prologueCallback(callback) -{ -} - -QV8GCCallback::Node::~Node() -{ - node.remove(); -} - -/* - Ensure that each persistent handle is strong if it has CPP ownership - and has no implicitly JS owned object owner in its parent chain, and - weak otherwise. - - Any weak handle whose parent object is still alive will have an implicit - reference (between the parent and the handle) added, so that it will - not be collected. - - Note that this callback is registered only for kGCTypeMarkSweepCompact - collection cycles, as it is during collection cycles of that type - in which weak persistent handle callbacks are called when required. - */ -void QV8GCCallback::garbageCollectorPrologueCallback(v8::GCType, v8::GCCallbackFlags) -{ - if (!QV8Engine::hasThreadData()) - return; - - QV8Engine::ThreadData *td = QV8Engine::threadData(); - QV8GCCallback::Node *currNode = td->gcCallbackNodes.first(); - - while (currNode) { - // The client which adds itself to the list is responsible - // for maintaining the correct implicit references in the - // specified callback. - currNode->prologueCallback(currNode); - currNode = td->gcCallbackNodes.next(currNode); - } -} - -void QV8GCCallback::addGcCallbackNode(QV8GCCallback::Node *node) -{ - QV8Engine::ThreadData *td = QV8Engine::threadData(); - td->gcCallbackNodes.insert(node); -} - -QV8Engine::ThreadData::ThreadData() - : gcPrologueCallbackRegistered(false) -{ - if (!v8::Isolate::GetCurrent()) { - isolate = v8::Isolate::New(); - isolate->Enter(); - } else { - isolate = 0; - } -} - -QV8Engine::ThreadData::~ThreadData() -{ - if (isolate) { - isolate->Exit(); - isolate->Dispose(); - isolate = 0; - } + return QV4::Value::fromString(m_v4Engine->newString(string)); } QT_END_NAMESPACE diff --git a/src/qml/qml/v8/qv8engine_impl_p.h b/src/qml/qml/v8/qv8engine_impl_p.h deleted file mode 100644 index 8879b67ebb..0000000000 --- a/src/qml/qml/v8/qv8engine_impl_p.h +++ /dev/null @@ -1,172 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QV8ENGINE_IMPL_P_H -#define QV8ENGINE_IMPL_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "qv8engine_p.h" -#include "qjsvalue_p.h" -#include "qjsconverter_p.h" -#include "qjsvalueiterator_p.h" - -QT_BEGIN_NAMESPACE - -inline v8::Handle<v8::Value> QV8Engine::makeJSValue(bool value) -{ - return value ? v8::True() : v8::False(); -} - -inline v8::Local<v8::Value> QV8Engine::makeJSValue(int value) -{ - return v8::Integer::New(value); -} - -inline v8::Local<v8::Value> QV8Engine::makeJSValue(uint value) -{ - return v8::Integer::NewFromUnsigned(value); -} - -inline v8::Local<v8::Value> QV8Engine::makeJSValue(double value) -{ - return v8::Number::New(value); -} - -inline v8::Handle<v8::Value> QV8Engine::makeJSValue(QJSValue::SpecialValue value) { - if (value == QJSValue::NullValue) - return v8::Null(); - return v8::Undefined(); -} - -inline v8::Local<v8::Value> QV8Engine::makeJSValue(const QString &value) -{ - return QJSConverter::toString(value); -} - -class QtScriptBagCleaner -{ -public: - template<class T> - void operator () (T* value) const - { - value->reinitialize(); - } - void operator () (QJSValueIteratorPrivate *iterator) const - { - iterator->invalidate(); - } -}; - -inline void QV8Engine::registerValue(QJSValuePrivate *data) -{ - m_values.insert(data); -} - -inline void QV8Engine::unregisterValue(QJSValuePrivate *data) -{ - m_values.remove(data); -} - -inline void QV8Engine::invalidateAllValues() -{ - ValueList::iterator it; - for (it = m_values.begin(); it != m_values.end(); it = it.erase()) - (*it)->invalidate(); - Q_ASSERT(m_values.isEmpty()); -} - -inline void QV8Engine::registerValueIterator(QJSValueIteratorPrivate *data) -{ - m_valueIterators.insert(data); -} - -inline void QV8Engine::unregisterValueIterator(QJSValueIteratorPrivate *data) -{ - m_valueIterators.remove(data); -} - -inline void QV8Engine::invalidateAllIterators() -{ - ValueIteratorList::iterator it; - for (it = m_valueIterators.begin(); it != m_valueIterators.end(); it = it.erase()) - (*it)->invalidate(); - Q_ASSERT(m_valueIterators.isEmpty()); -} - -/*! - \internal - \note property can be index (v8::Integer) or a property (v8::String) name, according to ECMA script - property would be converted to a string. -*/ -inline QJSValuePrivate::PropertyFlags QV8Engine::getPropertyFlags(v8::Handle<v8::Object> object, v8::Handle<v8::Value> property) -{ - QJSValuePrivate::PropertyFlags flags = m_originalGlobalObject.getPropertyFlags(object, property); - return flags; -} - -QScriptPassPointer<QJSValuePrivate> QV8Engine::evaluate(const QString& program, const QString& fileName, quint16 lineNumber) -{ - v8::TryCatch tryCatch; - v8::ScriptOrigin scriptOrigin(QJSConverter::toString(fileName), v8::Integer::New(lineNumber - 1)); - v8::Handle<v8::Script> script; - script = v8::Script::Compile(QJSConverter::toString(program), &scriptOrigin); - if (script.IsEmpty()) { - // TODO: Why don't we get the exception, as with Script::Compile()? - // Q_ASSERT(tryCatch.HasCaught()); - v8::Handle<v8::Value> error = v8::Exception::SyntaxError(v8::String::New("")); - return new QJSValuePrivate(this, error); - } - return evaluate(script, tryCatch); -} - -QT_END_NAMESPACE - -#endif // QV8ENGINE_IMPL_P_H diff --git a/src/qml/qml/v8/qv8engine_p.h b/src/qml/qml/v8/qv8engine_p.h index 5ae0963178..61db8a79b3 100644 --- a/src/qml/qml/v8/qv8engine_p.h +++ b/src/qml/qml/v8/qv8engine_p.h @@ -62,39 +62,24 @@ #include <QtCore/QElapsedTimer> #include <QtCore/QThreadStorage> -#include <private/qv8_p.h> #include <qjsengine.h> #include <qjsvalue.h> -#include "qjsvalue_p.h" #include "qjsvalueiterator_p.h" -#include "qscriptoriginalglobalobject_p.h" -#include "qscripttools_p.h" +#include "private/qintrusivelist_p.h" #include <private/qqmlpropertycache_p.h> -#include "qv8objectresource_p.h" -#include "qv8contextwrapper_p.h" -#include "qv8qobjectwrapper_p.h" -#include "qv8stringwrapper_p.h" -#include "qv8typewrapper_p.h" -#include "qv8listwrapper_p.h" -#include "qv8variantwrapper_p.h" -#include "qv8valuetypewrapper_p.h" -#include "qv8sequencewrapper_p.h" -#include "qv8jsonwrapper_p.h" - -namespace v8 { - -// Needed for V8ObjectSet -inline uint qHash(const v8::Handle<v8::Object> &object, uint seed = 0) -{ - return (object->GetIdentityHash() ^ seed); -} - -} +#include <private/qv4qobjectwrapper_p.h> +#include <private/qv4value_p.h> +#include <private/qv4object_p.h> QT_BEGIN_NAMESPACE +namespace QV4 { + struct ArrayObject; + struct ExecutionEngine; + struct Value; +} // Uncomment the following line to enable global handle debugging. When enabled, all the persistent // handles allocated using qPersistentNew() (or registered with qPersistentRegsiter()) and disposed @@ -102,32 +87,11 @@ QT_BEGIN_NAMESPACE // a handle, qFatal() is called. // #define QML_GLOBAL_HANDLE_DEBUGGING -#define V8ENGINE() ((QV8Engine *)v8::External::Cast(*args.Data())->Value()) -#define V8FUNCTION(function, engine) v8::FunctionTemplate::New(function, v8::External::New((QV8Engine*)engine))->GetFunction() -#define V8THROW_ERROR(string) { \ - v8::ThrowException(v8::Exception::Error(v8::String::New(string))); \ - return v8::Handle<v8::Value>(); \ -} -#define V8THROW_TYPE(string) { \ - v8::ThrowException(v8::Exception::TypeError(v8::String::New(string))); \ - return v8::Handle<v8::Value>(); \ -} -#define V8ENGINE_ACCESSOR() ((QV8Engine *)v8::External::Cast(*info.Data())->Value()); -#define V8THROW_ERROR_SETTER(string) { \ - v8::ThrowException(v8::Exception::Error(v8::String::New(string))); \ - return; \ -} +#define V4THROW_ERROR(string) \ + ctx->throwError(QString::fromUtf8(string)); -#define V8ASSERT_TYPE(condition, string) \ - if (!(condition)) { \ - v8::ThrowException(v8::Exception::TypeError(v8::String::New(string))); \ - return v8::Handle<v8::Value>(); \ - } -#define V8ASSERT_TYPE_SETTER(condition, string) \ - if (!(condition)) { \ - v8::ThrowException(v8::Exception::TypeError(v8::String::New(string))); \ - return; \ - } +#define V4THROW_TYPE(string) \ + ctx->throwTypeError(QStringLiteral(string)); #define V8_DEFINE_EXTENSION(dataclass, datafunction) \ static inline dataclass *datafunction(QV8Engine *engine) \ @@ -147,19 +111,6 @@ QT_BEGIN_NAMESPACE return rv; \ } \ -template<class T> -inline T *v8_resource_cast(v8::Handle<v8::Object> object) { - QV8ObjectResource *resource = static_cast<QV8ObjectResource *>(object->GetExternalResource()); - return (resource && (quint32)resource->resourceType() == (quint32)T::V8ResourceType)?static_cast<T *>(resource):0; -} - -template<class T> -inline T *v8_resource_check(v8::Handle<v8::Object> object) { - T *resource = static_cast<T *>(object->GetExternalResource()); - Q_ASSERT(resource && resource->resourceType() == (quint32)T::V8ResourceType); - return resource; -} - // Used to allow a QObject method take and return raw V8 handles without having to expose // v8 in the public API. // Use like this: @@ -172,50 +123,52 @@ inline T *v8_resource_check(v8::Handle<v8::Object> object) { // valid during the call. If the return value isn't set within myMethod(), the will return // undefined. class QV8Engine; -class QQmlV8Function +class QQmlV4Function { public: - int Length() const { return _ac; } - v8::Local<v8::Value> operator[](int idx) { return (*_a)->Get(idx); } - QQmlContextData *context() { return _c; } - v8::Handle<v8::Object> qmlGlobal() { return *_g; } - void returnValue(v8::Handle<v8::Value> rv) { *_r = rv; } - QV8Engine *engine() const { return _e; } + int length() const { return argc; } + QV4::Value operator[](int idx) { return args[idx]; } + QQmlContextData *context() { return ctx; } + QV4::Value qmlGlobal() { return global; } + void setReturnValue(const QV4::Value &rv) { *retVal = rv; } + QV8Engine *engine() const { return e; } private: friend class QV8QObjectWrapper; - QQmlV8Function(); - QQmlV8Function(const QQmlV8Function &); - QQmlV8Function &operator=(const QQmlV8Function &); + friend struct QV4::QObjectMethod; + QQmlV4Function(); + QQmlV4Function(const QQmlV4Function &); + QQmlV4Function &operator=(const QQmlV4Function &); - QQmlV8Function(int length, v8::Handle<v8::Object> &args, - v8::Handle<v8::Value> &rv, v8::Handle<v8::Object> &global, + QQmlV4Function(int length, QV4::Value *args, + QV4::Value *rv, const QV4::Value &global, QQmlContextData *c, QV8Engine *e) - : _ac(length), _a(&args), _r(&rv), _g(&global), _c(c), _e(e) {} - - int _ac; - v8::Handle<v8::Object> *_a; - v8::Handle<v8::Value> *_r; - v8::Handle<v8::Object> *_g; - QQmlContextData *_c; - QV8Engine *_e; + : argc(length), args(args), retVal(rv), global(global), ctx(c), e(e) {} + + int argc; + QV4::Value *args; + QV4::Value *retVal; + QV4::Value global; + QQmlContextData *ctx; + QV8Engine *e; }; -class QQmlV8Handle +class Q_QML_PRIVATE_EXPORT QQmlV4Handle { public: - QQmlV8Handle() : d(0) {} - QQmlV8Handle(const QQmlV8Handle &other) : d(other.d) {} - QQmlV8Handle &operator=(const QQmlV8Handle &other) { d = other.d; return *this; } - - static QQmlV8Handle fromHandle(v8::Handle<v8::Value> h) { - return QQmlV8Handle(*h); - } - v8::Handle<v8::Value> toHandle() const { - return v8::Handle<v8::Value>((v8::Value *)d); + QQmlV4Handle() : d(0) {} + QQmlV4Handle(const QQmlV4Handle &other) : d(other.d) {} + QQmlV4Handle &operator=(const QQmlV4Handle &other) { d = other.d; return *this; } + explicit QQmlV4Handle(const QV4::Value &v) : d(v.val) {} + + QV4::Value toValue() const { + QV4::Value v; + v.val = d; + return v; } + private: - QQmlV8Handle(void *d) : d(d) {} - void *d; + QQmlV4Handle(quint64 h) : d(h) {} + quint64 d; }; class QObject; @@ -224,39 +177,17 @@ class QQmlValueType; class QNetworkAccessManager; class QQmlContextData; -class Q_AUTOTEST_EXPORT QV8GCCallback -{ -private: - class ThreadData; -public: - static void garbageCollectorPrologueCallback(v8::GCType, v8::GCCallbackFlags); - static void registerGcPrologueCallback(); - - class Q_AUTOTEST_EXPORT Node { - public: - typedef void (*PrologueCallback)(Node *node); - Node(PrologueCallback callback); - ~Node(); - - QIntrusiveListNode node; - PrologueCallback prologueCallback; - }; - - static void addGcCallbackNode(Node *node); -}; - class Q_QML_PRIVATE_EXPORT QV8Engine { - typedef QSet<v8::Handle<v8::Object> > V8ObjectSet; + friend class QJSEngine; + typedef QSet<QV4::Object *> V8ObjectSet; public: static QV8Engine* get(QJSEngine* q) { Q_ASSERT(q); return q->handle(); } - static QJSEngine* get(QV8Engine* d) { Q_ASSERT(d); return d->q; } +// static QJSEngine* get(QV8Engine* d) { Q_ASSERT(d); return d->q; } + static QV4::ExecutionEngine *getV4(QJSEngine *q) { return q->handle()->m_v4Engine; } + static QV4::ExecutionEngine *getV4(QV8Engine *d) { return d->m_v4Engine; } - enum ContextOwnership { - AdoptCurrentContext, - CreateNewContext - }; - QV8Engine(QJSEngine* qq, ContextOwnership ownership = CreateNewContext); + QV8Engine(QJSEngine* qq); virtual ~QV8Engine(); // This enum should be in sync with QQmlEngine::ObjectOwnership @@ -269,24 +200,8 @@ public: void initQmlGlobalObject(); void setEngine(QQmlEngine *engine); QQmlEngine *engine() { return m_engine; } - v8::Local<v8::Object> global() { return m_context->Global(); } - v8::Handle<v8::Context> context() const { return m_context; } - - inline void registerValue(QJSValuePrivate *data); - inline void unregisterValue(QJSValuePrivate *data); - inline void invalidateAllValues(); - - inline void registerValueIterator(QJSValueIteratorPrivate *data); - inline void unregisterValueIterator(QJSValueIteratorPrivate *data); - inline void invalidateAllIterators(); - - QV8ContextWrapper *contextWrapper() { return &m_contextWrapper; } - QV8QObjectWrapper *qobjectWrapper() { return &m_qobjectWrapper; } - QV8TypeWrapper *typeWrapper() { return &m_typeWrapper; } - QV8ListWrapper *listWrapper() { return &m_listWrapper; } - QV8VariantWrapper *variantWrapper() { return &m_variantWrapper; } - QV8ValueTypeWrapper *valueTypeWrapper() { return &m_valueTypeWrapper; } - QV8SequenceWrapper *sequenceWrapper() { return &m_sequenceWrapper; } + QJSEngine *publicEngine() { return q; } + QV4::Value global(); void *xmlHttpRequestData() { return m_xmlHttpRequestData; } @@ -295,55 +210,13 @@ public: QQmlContextData *callingContext(); - v8::Local<v8::Array> getOwnPropertyNames(v8::Handle<v8::Object>); - inline QJSValuePrivate::PropertyFlags getPropertyFlags(v8::Handle<v8::Object> object, v8::Handle<v8::Value> property); - void freezeObject(v8::Handle<v8::Value>); - - inline QString toString(v8::Handle<v8::Value> string); - inline QString toString(v8::Handle<v8::String> string); - static QString toStringStatic(v8::Handle<v8::Value>); - static QString toStringStatic(v8::Handle<v8::String>); - static inline bool startsWithUpper(v8::Handle<v8::String>); - - QVariant toVariant(v8::Handle<v8::Value>, int typeHint); - v8::Handle<v8::Value> fromVariant(const QVariant &); - inline bool isVariant(v8::Handle<v8::Value>); - - // Compile \a source (from \a fileName at \a lineNumber) in QML mode - v8::Local<v8::Script> qmlModeCompile(const QString &source, - const QString &fileName = QString(), - quint16 lineNumber = 1); - v8::Local<v8::Script> qmlModeCompile(const char *source, int sourceLength = -1, - const QString &fileName = QString(), - quint16 lineNumber = 1); - - // Return the QML global "scope" object for the \a ctxt context and \a scope object. - inline v8::Local<v8::Object> qmlScope(QQmlContextData *ctxt, QObject *scope); - - // Return a JS wrapper for the given QObject \a object - inline v8::Handle<v8::Value> newQObject(QObject *object); - inline v8::Handle<v8::Value> newQObject(QObject *object, const ObjectOwnership ownership); - inline bool isQObject(v8::Handle<v8::Value>); - inline QObject *toQObject(v8::Handle<v8::Value>); - - // Return a JS string for the given QString \a string - inline v8::Local<v8::String> toString(const QString &string); - - // Create a new value type object - inline v8::Handle<v8::Value> newValueType(QObject *, int coreIndex, QQmlValueType *); - inline v8::Handle<v8::Value> newValueType(const QVariant &, QQmlValueType *); - inline bool isValueType(v8::Handle<v8::Value>) const; - inline QVariant toValueType(v8::Handle<v8::Value> obj); + void freezeObject(const QV4::Value &value); - // Create a new sequence type object - inline v8::Handle<v8::Value> newSequence(int sequenceType, QObject *, int coreIndex, bool *succeeded); + QVariant toVariant(const QV4::Value &value, int typeHint); + QV4::Value fromVariant(const QVariant &); - // Create a new QVariant object. This doesn't examine the type of the variant, but always returns - // a QVariant wrapper - inline v8::Handle<v8::Value> newQVariant(const QVariant &); - - // Return the JS string key for the "function is a binding" flag - inline v8::Handle<v8::String> bindingFlagKey() const; + // Return a JS string for the given QString \a string + QV4::Value toString(const QString &string); // Return the network access manager for this engine. By default this returns the network // access manager of the QQmlEngine. It is overridden in the case of a threaded v8 @@ -354,15 +227,7 @@ public: const QStringHash<bool> &illegalNames() const; inline void collectGarbage() { gc(); } - static void gc(); - - v8::Handle<v8::Value> throwException(v8::Handle<v8::Value> value); - -#ifdef QML_GLOBAL_HANDLE_DEBUGGING - // Used for handle debugging - static void registerHandle(void *); - static void releaseHandle(void *); -#endif + void gc(); static QMutex *registrationMutex(); static int registerExtension(); @@ -370,49 +235,25 @@ public: inline Deletable *extensionData(int) const; void setExtensionData(int, Deletable *); - inline v8::Handle<v8::Value> makeJSValue(bool value); - inline v8::Local<v8::Value> makeJSValue(int value); - inline v8::Local<v8::Value> makeJSValue(uint value); - inline v8::Local<v8::Value> makeJSValue(double value); - inline v8::Handle<v8::Value> makeJSValue(QJSValue::SpecialValue value); - inline v8::Local<v8::Value> makeJSValue(const QString &value); - - inline QScriptPassPointer<QJSValuePrivate> evaluate(const QString &program, const QString &fileName = QString(), quint16 lineNumber = 1); - QScriptPassPointer<QJSValuePrivate> evaluate(v8::Handle<v8::Script> script, v8::TryCatch& tryCatch); - - QScriptPassPointer<QJSValuePrivate> newArray(uint length); - v8::Local<v8::Object> newVariant(const QVariant &variant); - - v8::Local<v8::Array> variantListToJS(const QVariantList &lst); - inline QVariantList variantListFromJS(v8::Handle<v8::Array> jsArray) - { V8ObjectSet visitedObjects; return variantListFromJS(jsArray, visitedObjects); } + QV4::Value variantListToJS(const QVariantList &lst); + inline QVariantList variantListFromJS(QV4::ArrayObject *array) + { V8ObjectSet visitedObjects; return variantListFromJS(array, visitedObjects); } - v8::Local<v8::Object> variantMapToJS(const QVariantMap &vmap); - inline QVariantMap variantMapFromJS(v8::Handle<v8::Object> jsObject) - { V8ObjectSet visitedObjects; return variantMapFromJS(jsObject, visitedObjects); } + QV4::Value variantMapToJS(const QVariantMap &vmap); + inline QVariantMap variantMapFromJS(QV4::Object *object) + { V8ObjectSet visitedObjects; return variantMapFromJS(object, visitedObjects); } - v8::Handle<v8::Value> variantToJS(const QVariant &value); - inline QVariant variantFromJS(v8::Handle<v8::Value> value) + QV4::Value variantToJS(const QVariant &value); + inline QVariant variantFromJS(const QV4::Value &value) { V8ObjectSet visitedObjects; return variantFromJS(value, visitedObjects); } - v8::Handle<v8::Value> jsonValueToJS(const QJsonValue &value); - QJsonValue jsonValueFromJS(v8::Handle<v8::Value> value); - v8::Local<v8::Object> jsonObjectToJS(const QJsonObject &object); - QJsonObject jsonObjectFromJS(v8::Handle<v8::Value> value); - v8::Local<v8::Array> jsonArrayToJS(const QJsonArray &array); - QJsonArray jsonArrayFromJS(v8::Handle<v8::Value> value); + QV4::Value metaTypeToJS(int type, const void *data); + bool metaTypeFromJS(const QV4::Value &value, int type, void *data); - v8::Handle<v8::Value> metaTypeToJS(int type, const void *data); - bool metaTypeFromJS(v8::Handle<v8::Value> value, int type, void *data); - - bool convertToNativeQObject(v8::Handle<v8::Value> value, + bool convertToNativeQObject(const QV4::Value &value, const QByteArray &targetType, void **result); - QVariant &variantValue(v8::Handle<v8::Value> value); - - QJSValue scriptValueFromInternal(v8::Handle<v8::Value>) const; - // used for console.time(), console.timeEnd() void startTimer(const QString &timerName); qint64 stopTimer(const QString &timerName, bool *wasRunning); @@ -420,54 +261,15 @@ public: // used for console.count() int consoleCountHelper(const QString &file, quint16 line, quint16 column); - QObject *qtObjectFromJS(v8::Handle<v8::Value> value); - - static QDateTime qtDateTimeFromJsDate(double jsDate); - - void addRelationshipForGC(QObject *object, v8::Persistent<v8::Value> handle); - void addRelationshipForGC(QObject *object, QObject *other); - - static v8::Handle<v8::Value> getPlatform(v8::Local<v8::String> property, const v8::AccessorInfo &info); - static v8::Handle<v8::Value> getApplication(v8::Local<v8::String> property, const v8::AccessorInfo &info); -#ifndef QT_NO_IM - static v8::Handle<v8::Value> getInputMethod(v8::Local<v8::String> property, const v8::AccessorInfo &info); -#endif - - struct ThreadData { - ThreadData(); - ~ThreadData(); - v8::Isolate* isolate; - bool gcPrologueCallbackRegistered; - QIntrusiveList<QV8GCCallback::Node, &QV8GCCallback::Node::node> gcCallbackNodes; - }; - - static bool hasThreadData(); - static ThreadData* threadData(); - static void ensurePerThreadIsolate(); - - v8::Persistent<v8::Object> m_strongReferencer; + QObject *qtObjectFromJS(const QV4::Value &value); protected: QJSEngine* q; QQmlEngine *m_engine; - bool m_ownsV8Context; - v8::Persistent<v8::Context> m_context; - QScriptOriginalGlobalObject m_originalGlobalObject; - v8::Persistent<v8::String> m_bindingFlagKey; + QV4::ExecutionEngine *m_v4Engine; - QV8StringWrapper m_stringWrapper; - QV8ContextWrapper m_contextWrapper; - QV8QObjectWrapper m_qobjectWrapper; - QV8TypeWrapper m_typeWrapper; - QV8ListWrapper m_listWrapper; - QV8VariantWrapper m_variantWrapper; - QV8ValueTypeWrapper m_valueTypeWrapper; - QV8SequenceWrapper m_sequenceWrapper; - QV8JsonWrapper m_jsonWrapper; - - v8::Persistent<v8::Function> m_getOwnPropertyNames; - v8::Persistent<v8::Function> m_freezeObject; + QV4::PersistentValue m_freezeObject; void *m_xmlHttpRequestData; @@ -481,161 +283,18 @@ protected: QHash<QString, quint32> m_consoleCount; - QObject *m_platform; - QObject *m_application; - - QVariant toBasicVariant(v8::Handle<v8::Value>); + QVariant toBasicVariant(const QV4::Value &); - void initializeGlobal(v8::Handle<v8::Object>); - - double qtDateTimeToJsDate(const QDateTime &dt); + void initializeGlobal(); private: - QVariantList variantListFromJS(v8::Handle<v8::Array> jsArray, V8ObjectSet &visitedObjects); - QVariantMap variantMapFromJS(v8::Handle<v8::Object> jsObject, V8ObjectSet &visitedObjects); - QVariant variantFromJS(v8::Handle<v8::Value> value, V8ObjectSet &visitedObjects); - - static v8::Persistent<v8::Object> *findOwnerAndStrength(QObject *object, bool *shouldBeStrong); - - typedef QScriptIntrusiveList<QJSValuePrivate, &QJSValuePrivate::m_node> ValueList; - ValueList m_values; - typedef QScriptIntrusiveList<QJSValueIteratorPrivate, &QJSValueIteratorPrivate::m_node> ValueIteratorList; - ValueIteratorList m_valueIterators; + QVariantList variantListFromJS(QV4::ArrayObject *array, V8ObjectSet &visitedObjects); + QVariantMap variantMapFromJS(QV4::Object *object, V8ObjectSet &visitedObjects); + QVariant variantFromJS(const QV4::Value &value, V8ObjectSet &visitedObjects); Q_DISABLE_COPY(QV8Engine) }; -// Allocate a new Persistent handle. *ALL* persistent handles in QML must be allocated -// using this method. -template<class T> -v8::Persistent<T> qPersistentNew(v8::Handle<T> that) -{ - v8::Persistent<T> rv = v8::Persistent<T>::New(that); -#ifdef QML_GLOBAL_HANDLE_DEBUGGING - QV8Engine::registerHandle(*rv); -#endif - return rv; -} - -// Register a Persistent handle that was returned to you by V8 (such as by -// v8::Context::New). This allows us to do handle tracking on these handles too. -template<class T> -void qPersistentRegister(v8::Persistent<T> handle) -{ -#ifdef QML_GLOBAL_HANDLE_DEBUGGING - QV8Engine::registerHandle(*handle); -#else - Q_UNUSED(handle); -#endif -} - -// Dispose and clear a persistent handle. *ALL* persistent handles in QML must be -// disposed using this method. -template<class T> -void qPersistentDispose(v8::Persistent<T> &that) -{ -#ifdef QML_GLOBAL_HANDLE_DEBUGGING - QV8Engine::releaseHandle(*that); -#endif - that.Dispose(); - that.Clear(); -} - -QString QV8Engine::toString(v8::Handle<v8::Value> string) -{ - return m_stringWrapper.toString(string->ToString()); -} - -QString QV8Engine::toString(v8::Handle<v8::String> string) -{ - return m_stringWrapper.toString(string); -} - -bool QV8Engine::isVariant(v8::Handle<v8::Value> value) -{ - return m_variantWrapper.isVariant(value); -} - -v8::Local<v8::Object> QV8Engine::qmlScope(QQmlContextData *ctxt, QObject *scope) -{ - return m_contextWrapper.qmlScope(ctxt, scope); -} - -bool QV8Engine::isQObject(v8::Handle<v8::Value> obj) -{ - return obj->IsObject()?m_qobjectWrapper.isQObject(v8::Handle<v8::Object>::Cast(obj)):false; -} - -QObject *QV8Engine::toQObject(v8::Handle<v8::Value> obj) -{ - return obj->IsObject()?m_qobjectWrapper.toQObject(v8::Handle<v8::Object>::Cast(obj)):0; -} - -v8::Handle<v8::Value> QV8Engine::newQObject(QObject *object) -{ - return m_qobjectWrapper.newQObject(object); -} - -v8::Handle<v8::Value> QV8Engine::newQObject(QObject *object, const ObjectOwnership ownership) -{ - if (!object) - return v8::Null(); - - v8::Handle<v8::Value> result = newQObject(object); - QQmlData *ddata = QQmlData::get(object, true); - if (ownership == JavaScriptOwnership && ddata) { - ddata->indestructible = false; - ddata->explicitIndestructibleSet = true; - } - return result; -} - -v8::Local<v8::String> QV8Engine::toString(const QString &string) -{ - return m_stringWrapper.toString(string); -} - -v8::Handle<v8::Value> QV8Engine::newValueType(QObject *object, int property, QQmlValueType *type) -{ - return m_valueTypeWrapper.newValueType(object, property, type); -} - -v8::Handle<v8::Value> QV8Engine::newValueType(const QVariant &value, QQmlValueType *type) -{ - return m_valueTypeWrapper.newValueType(value, type); -} - -bool QV8Engine::isValueType(v8::Handle<v8::Value> obj) const -{ - return obj->IsObject()?m_valueTypeWrapper.isValueType(v8::Handle<v8::Object>::Cast(obj)):false; -} - -QVariant QV8Engine::toValueType(v8::Handle<v8::Value> obj) -{ - return obj->IsObject()?m_valueTypeWrapper.toVariant(v8::Handle<v8::Object>::Cast(obj)):QVariant(); -} - -v8::Handle<v8::Value> QV8Engine::newSequence(int sequenceType, QObject *object, int property, bool *succeeded) -{ - return m_sequenceWrapper.newSequence(sequenceType, object, property, succeeded); -} - -v8::Handle<v8::String> QV8Engine::bindingFlagKey() const -{ - return m_bindingFlagKey; -} - -// XXX Can this be made more optimal? It is called prior to resolving each and every -// unqualified name in QV8ContextWrapper. -bool QV8Engine::startsWithUpper(v8::Handle<v8::String> string) -{ - v8::String::Value value(string); - Q_ASSERT(*value != NULL); - uint16_t c = **value; - return (c >= 'A' && c <= 'Z') || - (c > 127 && QChar::category(c) == QChar::Letter_Uppercase); -} - QV8Engine::Deletable *QV8Engine::extensionData(int index) const { if (index < m_extensionData.count()) @@ -646,6 +305,6 @@ QV8Engine::Deletable *QV8Engine::extensionData(int index) const QT_END_NAMESPACE -Q_DECLARE_METATYPE(QQmlV8Handle) +Q_DECLARE_METATYPE(QQmlV4Handle) #endif // QQMLV8ENGINE_P_H diff --git a/src/qml/qml/v8/qv8include.cpp b/src/qml/qml/v8/qv8include.cpp deleted file mode 100644 index 101c3d24c3..0000000000 --- a/src/qml/qml/v8/qv8include.cpp +++ /dev/null @@ -1,245 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qv8include_p.h" - -#include <QtQml/qjsengine.h> -#include <QtNetwork/qnetworkrequest.h> -#include <QtNetwork/qnetworkreply.h> -#include <QtCore/qfile.h> -#include <QtQml/qqmlfile.h> - -#include <private/qqmlengine_p.h> - -QT_BEGIN_NAMESPACE - -QV8Include::QV8Include(const QUrl &url, QV8Engine *engine, QQmlContextData *context, - v8::Handle<v8::Object> qmlglobal, v8::Handle<v8::Function> callback) -: m_engine(engine), m_network(0), m_reply(0), m_url(url), m_redirectCount(0), m_context(context) -{ - m_qmlglobal = qPersistentNew<v8::Object>(qmlglobal); - if (!callback.IsEmpty()) - m_callbackFunction = qPersistentNew<v8::Function>(callback); - - m_resultObject = qPersistentNew<v8::Object>(resultValue()); - - m_network = engine->networkAccessManager(); - - QNetworkRequest request; - request.setUrl(url); - - m_reply = m_network->get(request); - QObject::connect(m_reply, SIGNAL(finished()), this, SLOT(finished())); -} - -QV8Include::~QV8Include() -{ - delete m_reply; m_reply = 0; - qPersistentDispose(m_callbackFunction); - qPersistentDispose(m_resultObject); -} - -v8::Local<v8::Object> QV8Include::resultValue(Status status) -{ - // XXX It seems inefficient to create this object from scratch each time. - v8::Local<v8::Object> result = v8::Object::New(); - result->Set(v8::String::New("OK"), v8::Integer::New(Ok)); - result->Set(v8::String::New("LOADING"), v8::Integer::New(Loading)); - result->Set(v8::String::New("NETWORK_ERROR"), v8::Integer::New(NetworkError)); - result->Set(v8::String::New("EXCEPTION"), v8::Integer::New(Exception)); - - result->Set(v8::String::New("status"), v8::Integer::New(status)); - - return result; -} - -void QV8Include::callback(QV8Engine *engine, v8::Handle<v8::Function> callback, v8::Handle<v8::Object> status) -{ - if (!callback.IsEmpty()) { - v8::Handle<v8::Value> args[] = { status }; - v8::TryCatch tc; - callback->Call(engine->global(), 1, args); - } -} - -v8::Handle<v8::Object> QV8Include::result() -{ - return m_resultObject; -} - -#define INCLUDE_MAXIMUM_REDIRECT_RECURSION 15 -void QV8Include::finished() -{ - m_redirectCount++; - - if (m_redirectCount < INCLUDE_MAXIMUM_REDIRECT_RECURSION) { - QVariant redirect = m_reply->attribute(QNetworkRequest::RedirectionTargetAttribute); - if (redirect.isValid()) { - m_url = m_url.resolved(redirect.toUrl()); - delete m_reply; - - QNetworkRequest request; - request.setUrl(m_url); - - m_reply = m_network->get(request); - QObject::connect(m_reply, SIGNAL(finished()), this, SLOT(finished())); - return; - } - } - - v8::HandleScope handle_scope; - - if (m_reply->error() == QNetworkReply::NoError) { - QByteArray data = m_reply->readAll(); - - QString code = QString::fromUtf8(data); - QQmlScript::Parser::extractPragmas(code); - - QQmlContextData *importContext = new QQmlContextData; - importContext->isInternal = true; - importContext->isJSContext = true; - importContext->url = m_url; - importContext->isPragmaLibraryContext = m_context->isPragmaLibraryContext; - importContext->setParent(m_context, true); - - v8::Context::Scope ctxtscope(m_engine->context()); - v8::TryCatch try_catch; - - v8::Local<v8::Script> script = m_engine->qmlModeCompile(code, m_url.toString()); - - if (!try_catch.HasCaught()) { - m_engine->contextWrapper()->addSubContext(m_qmlglobal, script, importContext); - script->Run(m_qmlglobal); - } - - if (try_catch.HasCaught()) { - m_resultObject->Set(v8::String::New("status"), v8::Integer::New(Exception)); - m_resultObject->Set(v8::String::New("exception"), try_catch.Exception()); - } else { - m_resultObject->Set(v8::String::New("status"), v8::Integer::New(Ok)); - } - } else { - m_resultObject->Set(v8::String::New("status"), v8::Integer::New(NetworkError)); - } - - callback(m_engine, m_callbackFunction, m_resultObject); - - disconnect(); - deleteLater(); -} - -/* - Documented in qv8engine.cpp -*/ -v8::Handle<v8::Value> QV8Include::include(const v8::Arguments &args) -{ - if (args.Length() == 0) - return v8::Undefined(); - - QV8Engine *engine = V8ENGINE(); - QQmlContextData *context = engine->callingContext(); - - if (!context || !context->isJSContext) - V8THROW_ERROR("Qt.include(): Can only be called from JavaScript files"); - - QUrl url(context->resolvedUrl(QUrl(engine->toString(args[0]->ToString())))); - - v8::Local<v8::Function> callbackFunction; - if (args.Length() >= 2 && args[1]->IsFunction()) - callbackFunction = v8::Local<v8::Function>::Cast(args[1]); - - QString localFile = QQmlFile::urlToLocalFileOrQrc(url); - - v8::Local<v8::Object> result; - - if (localFile.isEmpty()) { - - QV8Include *i = new QV8Include(url, engine, context, - v8::Context::GetCallingQmlGlobal(), - callbackFunction); - result = v8::Local<v8::Object>::New(i->result()); - - } else { - - QFile f(localFile); - - if (f.open(QIODevice::ReadOnly)) { - QByteArray data = f.readAll(); - QString code = QString::fromUtf8(data); - QQmlScript::Parser::extractPragmas(code); - - QQmlContextData *importContext = new QQmlContextData; - importContext->isInternal = true; - importContext->isJSContext = true; - importContext->url = url; - importContext->setParent(context, true); - - v8::TryCatch try_catch; - - v8::Local<v8::Script> script = engine->qmlModeCompile(code, url.toString()); - - if (!try_catch.HasCaught()) { - v8::Local<v8::Object> qmlglobal = v8::Context::GetCallingQmlGlobal(); - engine->contextWrapper()->addSubContext(qmlglobal, script, importContext); - script->Run(qmlglobal); - } - - if (try_catch.HasCaught()) { - result = resultValue(Exception); - result->Set(v8::String::New("exception"), try_catch.Exception()); - } else { - result = resultValue(Ok); - } - - } else { - result = resultValue(NetworkError); - } - - callback(engine, callbackFunction, result); - } - - if (result.IsEmpty()) - return v8::Undefined(); - else - return result; -} - -QT_END_NAMESPACE diff --git a/src/qml/qml/v8/qv8include_p.h b/src/qml/qml/v8/qv8include_p.h deleted file mode 100644 index 9f850e82b6..0000000000 --- a/src/qml/qml/v8/qv8include_p.h +++ /dev/null @@ -1,113 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QV8INCLUDE_P_H -#define QV8INCLUDE_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <QtCore/qobject.h> -#include <QtCore/qurl.h> - -#include <private/qqmlcontext_p.h> -#include <private/qqmlguard_p.h> - -#include <private/qv8_p.h> - -QT_BEGIN_NAMESPACE - -class QQmlEngine; -class QNetworkAccessManager; -class QNetworkReply; -class QV8Engine; -class QV8Include : public QObject -{ - Q_OBJECT -public: - enum Status { - Ok = 0, - Loading = 1, - NetworkError = 2, - Exception = 3 - }; - - static v8::Handle<v8::Value> include(const v8::Arguments &args); - -private slots: - void finished(); - -private: - QV8Include(const QUrl &, QV8Engine *, QQmlContextData *, - v8::Handle<v8::Object>, v8::Handle<v8::Function>); - ~QV8Include(); - - v8::Handle<v8::Object> result(); - - static v8::Local<v8::Object> resultValue(Status status = Loading); - static void callback(QV8Engine *engine, v8::Handle<v8::Function> callback, v8::Handle<v8::Object> status); - - QV8Engine *m_engine; - QNetworkAccessManager *m_network; - QQmlGuard<QNetworkReply> m_reply; - - QUrl m_url; - int m_redirectCount; - - v8::Persistent<v8::Function> m_callbackFunction; - v8::Persistent<v8::Object> m_resultObject; - - QQmlGuardedContextData m_context; - v8::Persistent<v8::Object> m_qmlglobal; -}; - -QT_END_NAMESPACE - -#endif // QV8INCLUDE_P_H - diff --git a/src/qml/qml/v8/qv8jsonwrapper.cpp b/src/qml/qml/v8/qv8jsonwrapper.cpp deleted file mode 100644 index 4d89551894..0000000000 --- a/src/qml/qml/v8/qv8jsonwrapper.cpp +++ /dev/null @@ -1,181 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qv8jsonwrapper_p.h" -#include "qv8engine_p.h" -#include "qjsconverter_impl_p.h" - -QT_BEGIN_NAMESPACE - -QV8JsonWrapper::QV8JsonWrapper() -: m_engine(0) -{ -} - -QV8JsonWrapper::~QV8JsonWrapper() -{ -} - -void QV8JsonWrapper::init(QV8Engine *engine) -{ - m_engine = engine; -} - -void QV8JsonWrapper::destroy() -{ -} - -v8::Handle<v8::Value> QV8JsonWrapper::fromJsonValue(const QJsonValue &value) -{ - if (value.isString()) - return QJSConverter::toString(value.toString()); - else if (value.isDouble()) - return v8::Number::New(value.toDouble()); - else if (value.isBool()) - return value.toBool() ? v8::True() : v8::False(); - else if (value.isArray()) - return fromJsonArray(value.toArray()); - else if (value.isObject()) - return fromJsonObject(value.toObject()); - else if (value.isNull()) - return v8::Null(); - else - return v8::Undefined(); -} - -QJsonValue QV8JsonWrapper::toJsonValue(v8::Handle<v8::Value> value, - V8ObjectSet &visitedObjects) -{ - if (value->IsString()) - return QJsonValue(QJSConverter::toString(value.As<v8::String>())); - else if (value->IsNumber()) - return QJsonValue(value->NumberValue()); - else if (value->IsBoolean()) - return QJsonValue(value->BooleanValue()); - else if (value->IsArray()) - return toJsonArray(value.As<v8::Array>(), visitedObjects); - else if (value->IsObject()) - return toJsonObject(value.As<v8::Object>(), visitedObjects); - else if (value->IsNull()) - return QJsonValue(QJsonValue::Null); - else - return QJsonValue(QJsonValue::Undefined); -} - -v8::Local<v8::Object> QV8JsonWrapper::fromJsonObject(const QJsonObject &object) -{ - v8::Local<v8::Object> v8object = v8::Object::New(); - for (QJsonObject::const_iterator it = object.begin(); it != object.end(); ++it) - v8object->Set(QJSConverter::toString(it.key()), fromJsonValue(it.value())); - return v8object; -} - -QJsonObject QV8JsonWrapper::toJsonObject(v8::Handle<v8::Value> value, - V8ObjectSet &visitedObjects) -{ - QJsonObject result; - if (!value->IsObject() || value->IsArray() || value->IsFunction()) - return result; - - v8::Handle<v8::Object> v8object(value.As<v8::Object>()); - if (visitedObjects.contains(v8object)) { - // Avoid recursion. - // For compatibility with QVariant{List,Map} conversion, we return an - // empty object (and no error is thrown). - return result; - } - - visitedObjects.insert(v8object); - - v8::Local<v8::Array> propertyNames = m_engine->getOwnPropertyNames(v8object); - uint32_t length = propertyNames->Length(); - for (uint32_t i = 0; i < length; ++i) { - v8::Local<v8::Value> name = propertyNames->Get(i); - v8::Local<v8::Value> propertyValue = v8object->Get(name); - if (!propertyValue->IsFunction()) - result.insert(QJSConverter::toString(name->ToString()), - toJsonValue(propertyValue, visitedObjects)); - } - - visitedObjects.remove(v8object); - - return result; -} - -v8::Local<v8::Array> QV8JsonWrapper::fromJsonArray(const QJsonArray &array) -{ - int size = array.size(); - v8::Local<v8::Array> v8array = v8::Array::New(size); - for (int i = 0; i < size; i++) - v8array->Set(i, fromJsonValue(array.at(i))); - return v8array; -} - -QJsonArray QV8JsonWrapper::toJsonArray(v8::Handle<v8::Value> value, - V8ObjectSet &visitedObjects) -{ - QJsonArray result; - if (!value->IsArray()) - return result; - - v8::Handle<v8::Array> v8array(value.As<v8::Array>()); - if (visitedObjects.contains(v8array)) { - // Avoid recursion. - // For compatibility with QVariant{List,Map} conversion, we return an - // empty array (and no error is thrown). - return result; - } - - visitedObjects.insert(v8array); - - uint32_t length = v8array->Length(); - for (uint32_t i = 0; i < length; ++i) { - v8::Local<v8::Value> element = v8array->Get(i); - if (!element->IsFunction()) - result.append(toJsonValue(element, visitedObjects)); - } - - visitedObjects.remove(v8array); - - return result; -} - -QT_END_NAMESPACE diff --git a/src/qml/qml/v8/qv8jsonwrapper_p.h b/src/qml/qml/v8/qv8jsonwrapper_p.h deleted file mode 100644 index eb4a197819..0000000000 --- a/src/qml/qml/v8/qv8jsonwrapper_p.h +++ /dev/null @@ -1,100 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QV8JSONWRAPPER_P_H -#define QV8JSONWRAPPER_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <QtCore/qglobal.h> -#include <QtCore/qset.h> -#include <private/qv8_p.h> - -#include <QtCore/qjsonarray.h> -#include <QtCore/qjsonobject.h> -#include <QtCore/qjsonvalue.h> - -QT_BEGIN_NAMESPACE - -class QV8Engine; -class QV8JsonWrapper -{ - typedef QSet<v8::Handle<v8::Object> > V8ObjectSet; -public: - QV8JsonWrapper(); - ~QV8JsonWrapper(); - - void init(QV8Engine *); - void destroy(); - - v8::Handle<v8::Value> fromJsonValue(const QJsonValue &value); - inline QJsonValue toJsonValue(v8::Handle<v8::Value> value) - { V8ObjectSet visitedObjects; return toJsonValue(value, visitedObjects); } - - v8::Local<v8::Object> fromJsonObject(const QJsonObject &object); - inline QJsonObject toJsonObject(v8::Handle<v8::Value> value) - { V8ObjectSet visitedObjects; return toJsonObject(value, visitedObjects); } - - v8::Local<v8::Array> fromJsonArray(const QJsonArray &array); - inline QJsonArray toJsonArray(v8::Handle<v8::Value> value) - { V8ObjectSet visitedObjects; return toJsonArray(value, visitedObjects); } - -private: - QJsonValue toJsonValue(v8::Handle<v8::Value> value, V8ObjectSet &visitedObjects); - QJsonObject toJsonObject(v8::Handle<v8::Value> value, V8ObjectSet &visitedObjects); - QJsonArray toJsonArray(v8::Handle<v8::Value> value, V8ObjectSet &visitedObjects); - - QV8Engine *m_engine; -}; - -QT_END_NAMESPACE - -#endif // QV8JSONWRAPPER_P_H - diff --git a/src/qml/qml/v8/qv8listwrapper.cpp b/src/qml/qml/v8/qv8listwrapper.cpp deleted file mode 100644 index d3ce9f8fc2..0000000000 --- a/src/qml/qml/v8/qv8listwrapper.cpp +++ /dev/null @@ -1,194 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qv8listwrapper_p.h" -#include "qv8engine_p.h" -#include <private/qqmllist_p.h> - -QT_BEGIN_NAMESPACE - -class QV8ListResource : public QV8ObjectResource -{ - V8_RESOURCE_TYPE(ListType) -public: - QV8ListResource(QV8Engine *engine) : QV8ObjectResource(engine) {} - - QQmlGuard<QObject> object; - QQmlListProperty<QObject> property; - int propertyType; -}; - -QV8ListWrapper::QV8ListWrapper() -: m_engine(0) -{ -} - -QV8ListWrapper::~QV8ListWrapper() -{ -} - -void QV8ListWrapper::init(QV8Engine *engine) -{ - m_engine = engine; - v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New(); - ft->InstanceTemplate()->SetFallbackPropertyHandler(Getter, Setter, 0, 0, Enumerator); - ft->InstanceTemplate()->SetIndexedPropertyHandler(IndexedGetter); - ft->InstanceTemplate()->SetAccessor(v8::String::New("length"), LengthGetter, 0, - v8::Handle<v8::Value>(), v8::DEFAULT, - v8::PropertyAttribute(v8::ReadOnly | v8::DontDelete | v8::DontEnum)); - ft->InstanceTemplate()->SetHasExternalResource(true); - m_constructor = qPersistentNew<v8::Function>(ft->GetFunction()); -} - -void QV8ListWrapper::destroy() -{ - qPersistentDispose(m_constructor); -} - -v8::Handle<v8::Value> QV8ListWrapper::newList(QObject *object, int propId, int propType) -{ - if (!object || propId == -1) - return v8::Null(); - - // XXX NewInstance() should be optimized - v8::Local<v8::Object> rv = m_constructor->NewInstance(); - QV8ListResource *r = new QV8ListResource(m_engine); - r->object = object; - r->propertyType = propType; - void *args[] = { &r->property, 0 }; - QMetaObject::metacall(object, QMetaObject::ReadProperty, propId, args); - rv->SetExternalResource(r); - return rv; -} - -v8::Handle<v8::Value> QV8ListWrapper::newList(const QQmlListProperty<QObject> &prop, int propType) -{ - // XXX NewInstance() should be optimized - v8::Local<v8::Object> rv = m_constructor->NewInstance(); - QV8ListResource *r = new QV8ListResource(m_engine); - r->object = prop.object; - r->property = prop; - r->propertyType = propType; - rv->SetExternalResource(r); - return rv; -} - -QVariant QV8ListWrapper::toVariant(v8::Handle<v8::Object> obj) -{ - QV8ListResource *resource = v8_resource_cast<QV8ListResource>(obj); - if (resource) return toVariant(resource); - else return QVariant(); -} - -QVariant QV8ListWrapper::toVariant(QV8ObjectResource *r) -{ - Q_ASSERT(r->resourceType() == QV8ObjectResource::ListType); - QV8ListResource *resource = static_cast<QV8ListResource *>(r); - - if (!resource->object) - return QVariant(); - - return QVariant::fromValue(QQmlListReferencePrivate::init(resource->property, resource->propertyType, - m_engine->engine())); -} - -v8::Handle<v8::Value> QV8ListWrapper::Getter(v8::Local<v8::String> property, - const v8::AccessorInfo &info) -{ - Q_UNUSED(property); - Q_UNUSED(info); - return v8::Handle<v8::Value>(); -} - -v8::Handle<v8::Value> QV8ListWrapper::Setter(v8::Local<v8::String> property, - v8::Local<v8::Value> value, - const v8::AccessorInfo &info) -{ - Q_UNUSED(property); - Q_UNUSED(info); - return value; -} - -v8::Handle<v8::Value> QV8ListWrapper::IndexedGetter(uint32_t index, const v8::AccessorInfo &info) -{ - QV8ListResource *resource = v8_resource_cast<QV8ListResource>(info.This()); - - if (!resource || resource->object.isNull()) return v8::Undefined(); - - quint32 count = resource->property.count?resource->property.count(&resource->property):0; - if (index < count && resource->property.at) { - return resource->engine->newQObject(resource->property.at(&resource->property, index)); - } else { - return v8::Undefined(); - } -} - -v8::Handle<v8::Value> QV8ListWrapper::LengthGetter(v8::Local<v8::String> property, - const v8::AccessorInfo &info) -{ - Q_UNUSED(property); - - QV8ListResource *resource = v8_resource_cast<QV8ListResource>(info.This()); - - if (!resource || resource->object.isNull()) return v8::Undefined(); - - quint32 count = resource->property.count?resource->property.count(&resource->property):0; - - return v8::Integer::NewFromUnsigned(count); -} - -v8::Handle<v8::Array> QV8ListWrapper::Enumerator(const v8::AccessorInfo &info) -{ - QV8ListResource *resource = v8_resource_cast<QV8ListResource>(info.This()); - - if (!resource || resource->object.isNull()) return v8::Array::New(); - - quint32 count = resource->property.count?resource->property.count(&resource->property):0; - - v8::Local<v8::Array> rv = v8::Array::New(count); - - for (uint ii = 0; ii < count; ++ii) - rv->Set(ii, v8::Number::New(ii)); - - return rv; -} - -QT_END_NAMESPACE diff --git a/src/qml/qml/v8/qv8listwrapper_p.h b/src/qml/qml/v8/qv8listwrapper_p.h deleted file mode 100644 index 3d780dc12c..0000000000 --- a/src/qml/qml/v8/qv8listwrapper_p.h +++ /dev/null @@ -1,97 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QV8LISTWRAPPER_P_H -#define QV8LISTWRAPPER_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <QtCore/qglobal.h> -#include <QtQml/qqmllist.h> -#include <private/qv8_p.h> - -QT_BEGIN_NAMESPACE - -class QV8Engine; -class QV8ObjectResource; -class QV8ListWrapper -{ -public: - QV8ListWrapper(); - ~QV8ListWrapper(); - - void init(QV8Engine *); - void destroy(); - - v8::Handle<v8::Value> newList(QObject *, int, int); - v8::Handle<v8::Value> newList(const QQmlListProperty<QObject> &, int); - QVariant toVariant(v8::Handle<v8::Object>); - QVariant toVariant(QV8ObjectResource *); - -private: - static v8::Handle<v8::Value> Getter(v8::Local<v8::String> property, - const v8::AccessorInfo &info); - static v8::Handle<v8::Value> Setter(v8::Local<v8::String> property, - v8::Local<v8::Value> value, - const v8::AccessorInfo &info); - static v8::Handle<v8::Value> IndexedGetter(uint32_t index, - const v8::AccessorInfo &info); - static v8::Handle<v8::Value> LengthGetter(v8::Local<v8::String> property, - const v8::AccessorInfo &info); - static v8::Handle<v8::Array> Enumerator(const v8::AccessorInfo &info); - - QV8Engine *m_engine; - v8::Persistent<v8::Function> m_constructor; -}; - -QT_END_NAMESPACE - -#endif // QV8LISTWRAPPER_P_H - diff --git a/src/qml/qml/v8/qv8objectresource_p.h b/src/qml/qml/v8/qv8objectresource_p.h deleted file mode 100644 index 78fd835431..0000000000 --- a/src/qml/qml/v8/qv8objectresource_p.h +++ /dev/null @@ -1,84 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QV8OBJECTRESOURCE_P_H -#define QV8OBJECTRESOURCE_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <QtCore/qglobal.h> -#include <private/qv8_p.h> - -QT_BEGIN_NAMESPACE - -#define V8_RESOURCE_TYPE(resourcetype) \ -public: \ - enum { V8ResourceType = QV8ObjectResource:: resourcetype }; \ - virtual QV8ObjectResource::ResourceType resourceType() const { return QV8ObjectResource:: resourcetype; } \ -private: - -class QV8Engine; -class QV8ObjectResource : public v8::Object::ExternalResource -{ -public: - QV8ObjectResource(QV8Engine *engine) : engine(engine) { Q_ASSERT(engine); } - enum ResourceType { ContextType, QObjectType, TypeType, ListType, VariantType, - ValueTypeType, XMLHttpRequestType, DOMNodeType, SQLDatabaseType, - ListModelType, Context2DType, Context2DStyleType, Context2DPixelArrayType, - ParticleDataType, SignalHandlerType, IncubatorType, VisualDataItemType, - SequenceType, LocaleDataType, ChangeSetArrayType }; - virtual ResourceType resourceType() const = 0; - - QV8Engine *engine; -}; - -QT_END_NAMESPACE - -#endif // QV8OBJECTRESOURCE_P_H diff --git a/src/qml/qml/v8/qv8profiler_p.h b/src/qml/qml/v8/qv8profiler_p.h index 458532dd7d..39a87f2156 100644 --- a/src/qml/qml/v8/qv8profiler_p.h +++ b/src/qml/qml/v8/qv8profiler_p.h @@ -39,4 +39,4 @@ ** ****************************************************************************/ -#include <private/v8-profiler.h> +//#include <private/v8-profiler.h> diff --git a/src/qml/qml/v8/qv8qobjectwrapper.cpp b/src/qml/qml/v8/qv8qobjectwrapper.cpp deleted file mode 100644 index 53f70ad132..0000000000 --- a/src/qml/qml/v8/qv8qobjectwrapper.cpp +++ /dev/null @@ -1,2283 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qv8qobjectwrapper_p.h" -#include "qv8contextwrapper_p.h" -#include "qv8engine_p.h" - -#include <private/qqmlguard_p.h> -#include <private/qqmlpropertycache_p.h> -#include <private/qqmlengine_p.h> -#include <private/qqmlvmemetaobject_p.h> -#include <private/qqmlbinding_p.h> -#include <private/qjsvalue_p.h> -#include <private/qscript_impl_p.h> -#include <private/qqmlaccessors_p.h> -#include <private/qqmlexpression_p.h> -#include <private/qqmlglobal_p.h> - -#include <QtQml/qjsvalue.h> -#include <QtCore/qjsonarray.h> -#include <QtCore/qjsonobject.h> -#include <QtCore/qjsonvalue.h> -#include <QtCore/qvarlengtharray.h> -#include <QtCore/qtimer.h> -#include <QtCore/qatomic.h> - -QT_BEGIN_NAMESPACE - -#if defined(__GNUC__) && !defined(__INTEL_COMPILER) -# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 405 -// The code in this file does not violate strict aliasing, but GCC thinks it does -// so turn off the warnings for us to have a clean build -# pragma GCC diagnostic ignored "-Wstrict-aliasing" -# endif -#endif - -#define QOBJECT_TOSTRING_INDEX -2 -#define QOBJECT_DESTROY_INDEX -3 - -// XXX TODO: Need to review all calls to QQmlEngine *engine() to confirm QObjects work -// correctly in a worker thread - -class QV8QObjectInstance : public QQmlGuard<QObject> -{ -public: - QV8QObjectInstance(QObject *o, QV8QObjectWrapper *w) - : QQmlGuard<QObject>(o), wrapper(w) - { - } - - ~QV8QObjectInstance() - { - qPersistentDispose(v8object); - } - - virtual void objectDestroyed(QObject *o) - { - if (wrapper) - wrapper->m_taintedObjects.remove(o); - delete this; - } - - v8::Persistent<v8::Object> v8object; - QV8QObjectWrapper *wrapper; -}; - -class QV8SignalHandlerResource : public QV8ObjectResource -{ - V8_RESOURCE_TYPE(SignalHandlerType) -public: - QV8SignalHandlerResource(QV8Engine *engine, QObject *object, int index); - - QQmlGuard<QObject> object; - int index; -}; - -namespace { - -template<typename A, typename B, typename C, typename D, typename E, - typename F, typename G, typename H> -class MaxSizeOf8 { - template<typename Z, typename X> - struct SMax { - char dummy[sizeof(Z) > sizeof(X) ? sizeof(Z) : sizeof(X)]; - }; -public: - static const size_t Size = sizeof(SMax<A, SMax<B, SMax<C, SMax<D, SMax<E, SMax<F, SMax<G, H> > > > > > >); -}; - -struct CallArgument { - inline CallArgument(); - inline ~CallArgument(); - inline void *dataPtr(); - - inline void initAsType(int type); - inline void fromValue(int type, QV8Engine *, v8::Handle<v8::Value>); - inline v8::Handle<v8::Value> toValue(QV8Engine *); - -private: - CallArgument(const CallArgument &); - - inline void cleanup(); - - union { - float floatValue; - double doubleValue; - quint32 intValue; - bool boolValue; - QObject *qobjectPtr; - - char allocData[MaxSizeOf8<QVariant, - QString, - QList<QObject *>, - QJSValue, - QQmlV8Handle, - QJsonArray, - QJsonObject, - QJsonValue>::Size]; - qint64 q_for_alignment; - }; - - // Pointers to allocData - union { - QString *qstringPtr; - QVariant *qvariantPtr; - QList<QObject *> *qlistPtr; - QJSValue *qjsValuePtr; - QQmlV8Handle *handlePtr; - QJsonArray *jsonArrayPtr; - QJsonObject *jsonObjectPtr; - QJsonValue *jsonValuePtr; - }; - - int type; -}; -} - -QV8QObjectResource::QV8QObjectResource(QV8Engine *engine, QObject *object) -: QV8ObjectResource(engine), object(object) -{ -} - -QV8SignalHandlerResource::QV8SignalHandlerResource(QV8Engine *engine, QObject *object, int index) -: QV8ObjectResource(engine), object(object), index(index) -{ -} - -static QAtomicInt objectIdCounter(1); - -QV8QObjectWrapper::QV8QObjectWrapper() -: m_engine(0), m_id(objectIdCounter.fetchAndAddOrdered(1)) -{ -} - -QV8QObjectWrapper::~QV8QObjectWrapper() -{ - for (TaintedHash::Iterator iter = m_taintedObjects.begin(); - iter != m_taintedObjects.end(); - ++iter) { - (*iter)->wrapper = 0; - } - m_taintedObjects.clear(); -} - -void QV8QObjectWrapper::destroy() -{ - qDeleteAll(m_connections); - m_connections.clear(); - - qPersistentDispose(m_hiddenObject); - qPersistentDispose(m_destroySymbol); - qPersistentDispose(m_toStringSymbol); - qPersistentDispose(m_signalHandlerConstructor); - qPersistentDispose(m_methodConstructor); - qPersistentDispose(m_constructor); - - QIntrusiveList<QV8QObjectResource, &QV8QObjectResource::weakResource>::iterator i = m_javaScriptOwnedWeakQObjects.begin(); - for (; i != m_javaScriptOwnedWeakQObjects.end(); ++i) { - QV8QObjectResource *resource = *i; - Q_ASSERT(resource); - deleteWeakQObject(resource, true); - } -} - -struct ReadAccessor { - static inline void Indirect(QObject *object, const QQmlPropertyData &property, - void *output, QQmlNotifier **n) - { - Q_ASSERT(n == 0); - Q_UNUSED(n); - - void *args[] = { output, 0 }; - QMetaObject::metacall(object, QMetaObject::ReadProperty, property.coreIndex, args); - } - - static inline void Direct(QObject *object, const QQmlPropertyData &property, - void *output, QQmlNotifier **n) - { - Q_ASSERT(n == 0); - Q_UNUSED(n); - - void *args[] = { output, 0 }; - object->qt_metacall(QMetaObject::ReadProperty, property.coreIndex, args); - } - - static inline void Accessor(QObject *object, const QQmlPropertyData &property, - void *output, QQmlNotifier **n) - { - Q_ASSERT(property.accessors); - - property.accessors->read(object, property.accessorData, output); - if (n) property.accessors->notifier(object, property.accessorData, n); - } -}; - -static inline v8::Handle<v8::Value> valueToHandle(QV8Engine *, int v) -{ return v8::Integer::New(v); } -static inline v8::Handle<v8::Value> valueToHandle(QV8Engine *, uint v) -{ return v8::Integer::NewFromUnsigned(v); } -static inline v8::Handle<v8::Value> valueToHandle(QV8Engine *, bool v) -{ return v8::Boolean::New(v); } -static inline v8::Handle<v8::Value> valueToHandle(QV8Engine *e, const QString &v) -{ return e->toString(v); } -static inline v8::Handle<v8::Value> valueToHandle(QV8Engine *, float v) -{ return v8::Number::New(v); } -static inline v8::Handle<v8::Value> valueToHandle(QV8Engine *, double v) -{ return v8::Number::New(v); } -static inline v8::Handle<v8::Value> valueToHandle(QV8Engine *e, QObject *v) -{ return e->newQObject(v); } - -template<typename T, void (*ReadFunction)(QObject *, const QQmlPropertyData &, - void *, QQmlNotifier **)> -static v8::Handle<v8::Value> GenericValueGetter(v8::Local<v8::String>, const v8::AccessorInfo &info) -{ - v8::Handle<v8::Object> This = info.This(); - QV8QObjectResource *resource = v8_resource_check<QV8QObjectResource>(This); - - QObject *object = resource->object; - if (QQmlData::wasDeleted(object)) return v8::Undefined(); - - QQmlPropertyData *property = - (QQmlPropertyData *)v8::External::Cast(*info.Data())->Value(); - - QQmlEngine *engine = resource->engine->engine(); - QQmlEnginePrivate *ep = engine?QQmlEnginePrivate::get(engine):0; - - T value = T(); - - if (ep && ep->propertyCapture) { - if (ReadFunction == ReadAccessor::Accessor && property->accessors->notifier) { - QQmlNotifier *notifier = 0; - ReadFunction(object, *property, &value, ¬ifier); - if (notifier) ep->captureProperty(notifier); - } else if (!property->isConstant()) { - ep->captureProperty(object, property->coreIndex, property->notifyIndex); - ReadFunction(object, *property, &value, 0); - } else { - ReadFunction(object, *property, &value, 0); - } - } else { - ReadFunction(object, *property, &value, 0); - } - - return valueToHandle(resource->engine, value); -} - -#define FAST_GETTER_FUNCTION(property, cpptype) \ - (property->hasAccessors()?((v8::AccessorGetter)GenericValueGetter<cpptype, &ReadAccessor::Accessor>):(property->isDirect()?((v8::AccessorGetter)GenericValueGetter<cpptype, &ReadAccessor::Direct>):((v8::AccessorGetter)GenericValueGetter<cpptype, &ReadAccessor::Indirect>))) - -static quint32 toStringHash = quint32(-1); -static quint32 destroyHash = quint32(-1); - -void QV8QObjectWrapper::init(QV8Engine *engine) -{ - m_engine = engine; - - m_toStringSymbol = qPersistentNew<v8::String>(v8::String::NewSymbol("toString")); - m_destroySymbol = qPersistentNew<v8::String>(v8::String::NewSymbol("destroy")); - m_hiddenObject = qPersistentNew<v8::Object>(v8::Object::New()); - - m_toStringString = QHashedV8String(m_toStringSymbol); - m_destroyString = QHashedV8String(m_destroySymbol); - - toStringHash = m_toStringString.hash(); - destroyHash = m_destroyString.hash(); - - { - v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New(); - ft->InstanceTemplate()->SetFallbackPropertyHandler(Getter, Setter, Query, 0, Enumerator); - ft->InstanceTemplate()->SetHasExternalResource(true); - m_constructor = qPersistentNew<v8::Function>(ft->GetFunction()); - } - { - v8::ScriptOrigin origin(m_hiddenObject); // Hack to allow us to identify these functions -#define CREATE_FUNCTION_SOURCE \ - "(function(method) { "\ - "return (function(object, data, qmlglobal) { "\ - "return (function() { "\ - "return method(object, data, qmlglobal, arguments.length, arguments); "\ - "});"\ - "});"\ - "})" - v8::Local<v8::Script> script = v8::Script::New(v8::String::New(CREATE_FUNCTION_SOURCE), &origin, 0, - v8::Handle<v8::String>(), v8::Script::NativeMode); -#undef CREATE_FUNCTION_SOURCE - v8::Local<v8::Function> fn = v8::Local<v8::Function>::Cast(script->Run()); - v8::Handle<v8::Value> invokeFn = v8::FunctionTemplate::New(Invoke)->GetFunction(); - v8::Handle<v8::Value> args[] = { invokeFn }; - v8::Local<v8::Function> createFn = v8::Local<v8::Function>::Cast(fn->Call(engine->global(), 1, args)); - m_methodConstructor = qPersistentNew<v8::Function>(createFn); - } - - v8::Local<v8::Function> connect = V8FUNCTION(Connect, engine); - v8::Local<v8::Function> disconnect = V8FUNCTION(Disconnect, engine); - - { - v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New(); - ft->InstanceTemplate()->SetHasExternalResource(true); - ft->PrototypeTemplate()->Set(v8::String::New("connect"), connect, v8::DontEnum); - ft->PrototypeTemplate()->Set(v8::String::New("disconnect"), disconnect, v8::DontEnum); - m_signalHandlerConstructor = qPersistentNew<v8::Function>(ft->GetFunction()); - } - - { - v8::Local<v8::Object> prototype = engine->global()->Get(v8::String::New("Function"))->ToObject()->Get(v8::String::New("prototype"))->ToObject(); - prototype->Set(v8::String::New("connect"), connect, v8::DontEnum); - prototype->Set(v8::String::New("disconnect"), disconnect, v8::DontEnum); - } -} - -bool QV8QObjectWrapper::isQObject(v8::Handle<v8::Object> obj) -{ - return v8_resource_cast<QV8QObjectResource>(obj) != 0; -} - -QObject *QV8QObjectWrapper::toQObject(v8::Handle<v8::Object> obj) -{ - QV8QObjectResource *r = v8_resource_cast<QV8QObjectResource>(obj); - return r?r->object:0; -} - -// r *MUST* be a QV8ObjectResource (r->type() == QV8ObjectResource::QObjectType) -QObject *QV8QObjectWrapper::toQObject(QV8ObjectResource *r) -{ - Q_ASSERT(r->resourceType() == QV8ObjectResource::QObjectType); - return static_cast<QV8QObjectResource *>(r)->object; -} - -// Load value properties -template<void (*ReadFunction)(QObject *, const QQmlPropertyData &, - void *, QQmlNotifier **)> -static v8::Handle<v8::Value> LoadProperty(QV8Engine *engine, QObject *object, - const QQmlPropertyData &property, - QQmlNotifier **notifier) -{ - Q_ASSERT(!property.isFunction()); - - if (property.isQObject()) { - QObject *rv = 0; - ReadFunction(object, property, &rv, notifier); - return engine->newQObject(rv); - } else if (property.isQList()) { - return engine->listWrapper()->newList(object, property.coreIndex, property.propType); - } else if (property.propType == QMetaType::QReal) { - qreal v = 0; - ReadFunction(object, property, &v, notifier); - return valueToHandle(engine, v); - } else if (property.propType == QMetaType::Int || property.isEnum()) { - int v = 0; - ReadFunction(object, property, &v, notifier); - return valueToHandle(engine, v); - } else if (property.propType == QMetaType::Bool) { - bool v = false; - ReadFunction(object, property, &v, notifier); - return valueToHandle(engine, v); - } else if (property.propType == QMetaType::QString) { - QString v; - ReadFunction(object, property, &v, notifier); - return valueToHandle(engine, v); - } else if (property.propType == QMetaType::UInt) { - uint v = 0; - ReadFunction(object, property, &v, notifier); - return valueToHandle(engine, v); - } else if (property.propType == QMetaType::Float) { - float v = 0; - ReadFunction(object, property, &v, notifier); - return valueToHandle(engine, v); - } else if (property.propType == QMetaType::Double) { - double v = 0; - ReadFunction(object, property, &v, notifier); - return valueToHandle(engine, v); - } else if (property.isV8Handle()) { - QQmlV8Handle handle; - ReadFunction(object, property, &handle, notifier); - return handle.toHandle(); - } else if (property.propType == qMetaTypeId<QJSValue>()) { - QJSValue v; - ReadFunction(object, property, &v, notifier); - return QJSValuePrivate::get(v)->asV8Value(engine); - } else if (property.isQVariant()) { - QVariant v; - ReadFunction(object, property, &v, notifier); - - if (QQmlValueTypeFactory::isValueType(v.userType())) { - if (QQmlValueType *valueType = QQmlValueTypeFactory::valueType(v.userType())) - return engine->newValueType(object, property.coreIndex, valueType); // VariantReference value-type. - } - - return engine->fromVariant(v); - } else if (QQmlValueTypeFactory::isValueType(property.propType)) { - Q_ASSERT(notifier == 0); - - if (QQmlValueType *valueType = QQmlValueTypeFactory::valueType(property.propType)) - return engine->newValueType(object, property.coreIndex, valueType); - } else { - Q_ASSERT(notifier == 0); - - // see if it's a sequence type - bool succeeded = false; - v8::Handle<v8::Value> retn = engine->newSequence(property.propType, object, property.coreIndex, - &succeeded); - if (succeeded) - return retn; - } - - if (property.propType == QMetaType::UnknownType) { - QMetaProperty p = object->metaObject()->property(property.coreIndex); - qWarning("QMetaProperty::read: Unable to handle unregistered datatype '%s' for property " - "'%s::%s'", p.typeName(), object->metaObject()->className(), p.name()); - return v8::Undefined(); - } else { - QVariant v(property.propType, (void *)0); - ReadFunction(object, property, v.data(), notifier); - return engine->fromVariant(v); - } -} - -v8::Handle<v8::Value> QV8QObjectWrapper::GetProperty(QV8Engine *engine, QObject *object, - v8::Handle<v8::Value> *objectHandle, - const QHashedV8String &property, - QQmlContextData *context, - QV8QObjectWrapper::RevisionMode revisionMode) -{ - // XXX More recent versions of V8 introduced "Callable" objects. It is possible that these - // will be a faster way of creating QObject method objects. - struct MethodClosure { - static v8::Handle<v8::Value> create(QV8Engine *engine, QObject *object, - v8::Handle<v8::Value> *objectHandle, - int index) { - v8::Handle<v8::Value> argv[] = { - objectHandle?*objectHandle:engine->newQObject(object), - v8::Integer::New(index) - }; - Q_ASSERT(argv[0]->IsObject()); - return engine->qobjectWrapper()->m_methodConstructor->Call(engine->global(), 2, argv); - } - static v8::Handle<v8::Value> createWithGlobal(QV8Engine *engine, QObject *object, - v8::Handle<v8::Value> *objectHandle, - int index) { - v8::Handle<v8::Value> argv[] = { - objectHandle?*objectHandle:engine->newQObject(object), - v8::Integer::New(index), - v8::Context::GetCallingQmlGlobal() - }; - Q_ASSERT(argv[0]->IsObject()); - return engine->qobjectWrapper()->m_methodConstructor->Call(engine->global(), 3, argv); - } - }; - - if (QQmlData::wasDeleted(object)) - return v8::Handle<v8::Value>(); - - { - // Comparing the hash first actually makes a measurable difference here, at least on x86 - quint32 hash = property.hash(); - if (hash == toStringHash && engine->qobjectWrapper()->m_toStringString == property) { - return MethodClosure::create(engine, object, objectHandle, QOBJECT_TOSTRING_INDEX); - } else if (hash == destroyHash && engine->qobjectWrapper()->m_destroyString == property) { - return MethodClosure::create(engine, object, objectHandle, QOBJECT_DESTROY_INDEX); - } - } - - QQmlPropertyData local; - QQmlPropertyData *result = 0; - { - QQmlData *ddata = QQmlData::get(object, false); - if (ddata && ddata->propertyCache) - result = ddata->propertyCache->property(property, object, context); - if (!result) - result = QQmlPropertyCache::property(engine->engine(), object, property, context, local); - } - - if (!result) - return v8::Handle<v8::Value>(); - - QQmlData::flushPendingBinding(object, result->coreIndex); - - if (revisionMode == QV8QObjectWrapper::CheckRevision && result->hasRevision()) { - QQmlData *ddata = QQmlData::get(object); - if (ddata && ddata->propertyCache && !ddata->propertyCache->isAllowedInRevision(result)) - return v8::Handle<v8::Value>(); - } - - if (result->isFunction() && !result->isVarProperty()) { - if (result->isVMEFunction()) { - QQmlVMEMetaObject *vmemo = QQmlVMEMetaObject::get(object); - Q_ASSERT(vmemo); - return vmemo->vmeMethod(result->coreIndex); - } else if (result->isV8Function()) { - return MethodClosure::createWithGlobal(engine, object, objectHandle, result->coreIndex); - } else if (result->isSignalHandler()) { - v8::Local<v8::Object> handler = engine->qobjectWrapper()->m_signalHandlerConstructor->NewInstance(); - QV8SignalHandlerResource *r = new QV8SignalHandlerResource(engine, object, result->coreIndex); - handler->SetExternalResource(r); - return handler; - } else { - return MethodClosure::create(engine, object, objectHandle, result->coreIndex); - } - } - - QQmlEnginePrivate *ep = - engine->engine()?QQmlEnginePrivate::get(engine->engine()):0; - - if (result->hasAccessors()) { - QQmlNotifier *n = 0; - QQmlNotifier **nptr = 0; - - if (ep && ep->propertyCapture && result->accessors->notifier) - nptr = &n; - - v8::Handle<v8::Value> rv = LoadProperty<ReadAccessor::Accessor>(engine, object, *result, nptr); - - if (result->accessors->notifier) { - if (n) ep->captureProperty(n); - } else { - ep->captureProperty(object, result->coreIndex, result->notifyIndex); - } - - return rv; - } - - if (ep && !result->isConstant()) - ep->captureProperty(object, result->coreIndex, result->notifyIndex); - - if (result->isVarProperty()) { - QQmlVMEMetaObject *vmemo = QQmlVMEMetaObject::get(object); - Q_ASSERT(vmemo); - return vmemo->vmeProperty(result->coreIndex); - } else if (result->isDirect()) { - return LoadProperty<ReadAccessor::Direct>(engine, object, *result, 0); - } else { - return LoadProperty<ReadAccessor::Indirect>(engine, object, *result, 0); - } -} - -// Setter for writable properties. Shared between the interceptor and fast property accessor -static inline void StoreProperty(QV8Engine *engine, QObject *object, QQmlPropertyData *property, - v8::Handle<v8::Value> value) -{ - QQmlBinding *newBinding = 0; - if (value->IsFunction()) { - if (value->ToObject()->GetHiddenValue(engine->bindingFlagKey()).IsEmpty()) { - if (!property->isVarProperty() && property->propType != qMetaTypeId<QJSValue>()) { - // assigning a JS function to a non var or QJSValue property or is not allowed. - QString error = QLatin1String("Cannot assign JavaScript function to "); - if (!QMetaType::typeName(property->propType)) - error += QLatin1String("[unknown property type]"); - else - error += QLatin1String(QMetaType::typeName(property->propType)); - v8::ThrowException(v8::Exception::Error(engine->toString(error))); - return; - } - } else { - // binding assignment. - QQmlContextData *context = engine->callingContext(); - v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(value); - - v8::Local<v8::StackTrace> trace = - v8::StackTrace::CurrentStackTrace(1, (v8::StackTrace::StackTraceOptions)(v8::StackTrace::kLineNumber | - v8::StackTrace::kScriptName)); - v8::Local<v8::StackFrame> frame = trace->GetFrame(0); - int lineNumber = frame->GetLineNumber(); - int columnNumber = frame->GetColumn(); - QString url = engine->toString(frame->GetScriptName()); - - newBinding = new QQmlBinding(&function, object, context, url, qmlSourceCoordinate(lineNumber), qmlSourceCoordinate(columnNumber)); - newBinding->setTarget(object, *property, context); - newBinding->setEvaluateFlags(newBinding->evaluateFlags() | - QQmlBinding::RequiresThisObject); - } - } - - QQmlAbstractBinding *oldBinding = - QQmlPropertyPrivate::setBinding(object, property->coreIndex, -1, newBinding); - if (oldBinding) - oldBinding->destroy(); - - if (!newBinding && property->isVarProperty()) { - // allow assignment of "special" values (null, undefined, function) to var properties - QQmlVMEMetaObject *vmemo = QQmlVMEMetaObject::get(object); - Q_ASSERT(vmemo); - vmemo->setVMEProperty(property->coreIndex, value); - return; - } - -#define PROPERTY_STORE(cpptype, value) \ - cpptype o = value; \ - int status = -1; \ - int flags = 0; \ - void *argv[] = { &o, 0, &status, &flags }; \ - QMetaObject::metacall(object, QMetaObject::WriteProperty, property->coreIndex, argv); - - if (value->IsNull() && property->isQObject()) { - PROPERTY_STORE(QObject*, 0); - } else if (value->IsUndefined() && property->isResettable()) { - void *a[] = { 0 }; - QMetaObject::metacall(object, QMetaObject::ResetProperty, property->coreIndex, a); - } else if (value->IsUndefined() && property->propType == qMetaTypeId<QVariant>()) { - PROPERTY_STORE(QVariant, QVariant()); - } else if (value->IsUndefined() && property->propType == QMetaType::QJsonValue) { - PROPERTY_STORE(QJsonValue, QJsonValue(QJsonValue::Undefined)); - } else if (!newBinding && property->propType == qMetaTypeId<QJSValue>()) { - PROPERTY_STORE(QJSValue, engine->scriptValueFromInternal(value)); - } else if (value->IsUndefined()) { - QString error = QLatin1String("Cannot assign [undefined] to "); - if (!QMetaType::typeName(property->propType)) - error += QLatin1String("[unknown property type]"); - else - error += QLatin1String(QMetaType::typeName(property->propType)); - v8::ThrowException(v8::Exception::Error(engine->toString(error))); - } else if (value->IsFunction()) { - // this is handled by the binding creation above - } else if (property->propType == QMetaType::Int && value->IsNumber()) { - PROPERTY_STORE(int, qRound(value->ToNumber()->Value())); - } else if (property->propType == QMetaType::QReal && value->IsNumber()) { - PROPERTY_STORE(qreal, qreal(value->ToNumber()->Value())); - } else if (property->propType == QMetaType::Float && value->IsNumber()) { - PROPERTY_STORE(float, float(value->ToNumber()->Value())); - } else if (property->propType == QMetaType::Double && value->IsNumber()) { - PROPERTY_STORE(double, double(value->ToNumber()->Value())); - } else if (property->propType == QMetaType::QString && value->IsString()) { - PROPERTY_STORE(QString, engine->toString(value->ToString())); - } else if (property->isVarProperty()) { - QQmlVMEMetaObject *vmemo = QQmlVMEMetaObject::get(object); - Q_ASSERT(vmemo); - vmemo->setVMEProperty(property->coreIndex, value); - } else { - QVariant v; - if (property->isQList()) - v = engine->toVariant(value, qMetaTypeId<QList<QObject *> >()); - else - v = engine->toVariant(value, property->propType); - - QQmlContextData *context = engine->callingContext(); - if (!QQmlPropertyPrivate::write(object, *property, v, context)) { - const char *valueType = 0; - if (v.userType() == QVariant::Invalid) valueType = "null"; - else valueType = QMetaType::typeName(v.userType()); - - const char *targetTypeName = QMetaType::typeName(property->propType); - if (!targetTypeName) - targetTypeName = "an unregistered type"; - - QString error = QLatin1String("Cannot assign ") + - QLatin1String(valueType) + - QLatin1String(" to ") + - QLatin1String(targetTypeName); - v8::ThrowException(v8::Exception::Error(engine->toString(error))); - } - } -} - -bool QV8QObjectWrapper::SetProperty(QV8Engine *engine, QObject *object, const QHashedV8String &property, QQmlContextData *context, - v8::Handle<v8::Value> value, QV8QObjectWrapper::RevisionMode revisionMode) -{ - if (engine->qobjectWrapper()->m_toStringString == property || - engine->qobjectWrapper()->m_destroyString == property) - return true; - - if (QQmlData::wasDeleted(object)) - return false; - - QQmlPropertyData local; - QQmlPropertyData *result = 0; - result = QQmlPropertyCache::property(engine->engine(), object, property, context, local); - - if (!result) - return false; - - if (revisionMode == QV8QObjectWrapper::CheckRevision && result->hasRevision()) { - QQmlData *ddata = QQmlData::get(object); - if (ddata && ddata->propertyCache && !ddata->propertyCache->isAllowedInRevision(result)) - return false; - } - - if (!result->isWritable() && !result->isQList()) { - QString error = QLatin1String("Cannot assign to read-only property \"") + - engine->toString(property.string()) + QLatin1Char('\"'); - v8::ThrowException(v8::Exception::Error(engine->toString(error))); - return true; - } - - StoreProperty(engine, object, result, value); - - return true; -} - -v8::Handle<v8::Value> QV8QObjectWrapper::Getter(v8::Local<v8::String> property, - const v8::AccessorInfo &info) -{ - QV8QObjectResource *resource = v8_resource_check<QV8QObjectResource>(info.This()); - - if (QQmlData::wasDeleted(resource->object)) - return v8::Handle<v8::Value>(); - - QObject *object = resource->object; - - QHashedV8String propertystring(property); - - QV8Engine *v8engine = resource->engine; - QQmlContextData *context = v8engine->callingContext(); - - v8::Handle<v8::Value> This = info.This(); - v8::Handle<v8::Value> result = GetProperty(v8engine, object, &This, propertystring, - context, QV8QObjectWrapper::IgnoreRevision); - if (!result.IsEmpty()) - return result; - - if (QV8Engine::startsWithUpper(property)) { - // Check for attached properties - if (context && context->imports) { - QQmlTypeNameCache::Result r = context->imports->query(propertystring); - - if (r.isValid()) { - if (r.scriptIndex != -1) { - return v8::Undefined(); - } else if (r.type) { - return v8engine->typeWrapper()->newObject(object, r.type, QV8TypeWrapper::ExcludeEnums); - } else if (r.importNamespace) { - return v8engine->typeWrapper()->newObject(object, context->imports, r.importNamespace, - QV8TypeWrapper::ExcludeEnums); - } - Q_ASSERT(!"Unreachable"); - } - } - } - - return v8::Handle<v8::Value>(); -} - -v8::Handle<v8::Value> QV8QObjectWrapper::Setter(v8::Local<v8::String> property, - v8::Local<v8::Value> value, - const v8::AccessorInfo &info) -{ - QV8QObjectResource *resource = v8_resource_check<QV8QObjectResource>(info.This()); - - if (QQmlData::wasDeleted(resource->object)) - return value; - - QObject *object = resource->object; - - QHashedV8String propertystring(property); - - QV8Engine *v8engine = resource->engine; - QQmlContextData *context = v8engine->callingContext(); - bool result = SetProperty(v8engine, object, propertystring, context, value, QV8QObjectWrapper::IgnoreRevision); - - if (!result) { - QString error = QLatin1String("Cannot assign to non-existent property \"") + - v8engine->toString(property) + QLatin1Char('\"'); - v8::ThrowException(v8::Exception::Error(v8engine->toString(error))); - return value; - } - - return value; -} - -v8::Handle<v8::Integer> QV8QObjectWrapper::Query(v8::Local<v8::String> property, - const v8::AccessorInfo &info) -{ - QV8QObjectResource *resource = v8_resource_check<QV8QObjectResource>(info.This()); - - if (resource->object.isNull()) - return v8::Handle<v8::Integer>(); - - QV8Engine *engine = resource->engine; - QObject *object = resource->object; - QQmlContextData *context = engine->callingContext(); - - QHashedV8String propertystring(property); - - QQmlPropertyData local; - QQmlPropertyData *result = 0; - result = QQmlPropertyCache::property(engine->engine(), object, propertystring, context, local); - - if (!result) - return v8::Handle<v8::Integer>(); - else if (!result->isWritable() && !result->isQList()) - return v8::Integer::New(v8::ReadOnly | v8::DontDelete); - else - return v8::Integer::New(v8::DontDelete); -} - -v8::Handle<v8::Array> QV8QObjectWrapper::Enumerator(const v8::AccessorInfo &info) -{ - QV8QObjectResource *resource = v8_resource_check<QV8QObjectResource>(info.This()); - - if (resource->object.isNull()) - return v8::Array::New(); - - QObject *object = resource->object; - - QStringList result; - - QQmlEnginePrivate *ep = resource->engine->engine() - ? QQmlEnginePrivate::get(resource->engine->engine()) - : 0; - - QQmlPropertyCache *cache = 0; - QQmlData *ddata = QQmlData::get(object); - if (ddata) - cache = ddata->propertyCache; - - if (!cache) { - cache = ep ? ep->cache(object) : 0; - if (cache) { - if (ddata) { cache->addref(); ddata->propertyCache = cache; } - } else { - // Not cachable - fall back to QMetaObject (eg. dynamic meta object) - const QMetaObject *mo = object->metaObject(); - int pc = mo->propertyCount(); - int po = mo->propertyOffset(); - for (int i=po; i<pc; ++i) - result << QString::fromUtf8(mo->property(i).name()); - } - } else { - result = cache->propertyNames(); - } - - v8::Local<v8::Array> rv = v8::Array::New(result.count()); - - for (int ii = 0; ii < result.count(); ++ii) - rv->Set(ii, resource->engine->toString(result.at(ii))); - - return rv; -} - -static void FastValueSetter(v8::Local<v8::String>, v8::Local<v8::Value> value, - const v8::AccessorInfo& info) -{ - QV8QObjectResource *resource = v8_resource_check<QV8QObjectResource>(info.This()); - - if (QQmlData::wasDeleted(resource->object)) - return; - - QObject *object = resource->object; - - QQmlPropertyData *property = - (QQmlPropertyData *)v8::External::Cast(*info.Data())->Value(); - - int index = property->coreIndex; - - QQmlData *ddata = QQmlData::get(object, false); - Q_ASSERT(ddata); - Q_ASSERT(ddata->propertyCache); - - QQmlPropertyData *pdata = ddata->propertyCache->property(index); - Q_ASSERT(pdata); - - Q_ASSERT(pdata->isWritable() || pdata->isQList()); - - StoreProperty(resource->engine, object, pdata, value); -} - -static void FastValueSetterReadOnly(v8::Local<v8::String> property, v8::Local<v8::Value>, - const v8::AccessorInfo& info) -{ - QV8QObjectResource *resource = v8_resource_check<QV8QObjectResource>(info.This()); - - if (QQmlData::wasDeleted(resource->object)) - return; - - QV8Engine *v8engine = resource->engine; - - QString error = QLatin1String("Cannot assign to read-only property \"") + - v8engine->toString(property) + QLatin1Char('\"'); - v8::ThrowException(v8::Exception::Error(v8engine->toString(error))); -} - -void QV8QObjectWrapper::WeakQObjectReferenceCallback(v8::Persistent<v8::Value> handle, void *wrapper) -{ - Q_ASSERT(handle->IsObject()); - v8::Handle<v8::Object> v8object = handle->ToObject(); - QV8QObjectResource *resource = v8_resource_check<QV8QObjectResource>(v8object); - Q_ASSERT(resource); - - static_cast<QV8QObjectWrapper*>(wrapper)->unregisterWeakQObjectReference(resource); - if (static_cast<QV8QObjectWrapper*>(wrapper)->deleteWeakQObject(resource, false)) { - // dispose - v8object->SetExternalResource(0); - delete resource; - qPersistentDispose(handle); - } else { - handle.MakeWeak(0, WeakQObjectReferenceCallback); // revive. - } -} - -static void WeakQObjectInstanceCallback(v8::Persistent<v8::Value> handle, void *data) -{ - QV8QObjectInstance *instance = (QV8QObjectInstance *)data; - instance->v8object.Clear(); - qPersistentDispose(handle); -} - -v8::Local<v8::Object> QQmlPropertyCache::newQObject(QObject *object, QV8Engine *engine) -{ - Q_ASSERT(object); - Q_ASSERT(this->engine); - - Q_ASSERT(QQmlData::get(object, false)); - Q_ASSERT(QQmlData::get(object, false)->propertyCache == this); - - // Setup constructor - if (constructor.IsEmpty()) { - v8::Local<v8::FunctionTemplate> ft; - - const QHashedString toString(QStringLiteral("toString")); - const QHashedString destroy(QStringLiteral("destroy")); - - // As we use hash linking, or with property overrides, it is possible that iterating - // over the values can yield duplicates. To combat this, we must unique'ify our properties. - const bool checkForDuplicates = stringCache.isLinked() || _hasPropertyOverrides; - - StringCache uniqueHash; - if (checkForDuplicates) - uniqueHash.reserve(stringCache.count()); - - // XXX TODO: Enables fast property accessors. These more than double the property access - // performance, but the cost of setting up this structure hasn't been measured so - // its not guaranteed that this is a win overall. We need to try and measure the cost. - for (StringCache::ConstIterator iter = stringCache.begin(); iter != stringCache.end(); ++iter) { - if (iter.equals(toString) || iter.equals(destroy)) - continue; - - if (checkForDuplicates) { - if (uniqueHash.contains(iter)) - continue; - uniqueHash.insert(iter); - } - - QQmlPropertyData *property = (*iter).second; - if (property->notFullyResolved()) resolve(property); - - if (property->isFunction()) - continue; - - v8::AccessorGetter fastgetter = 0; - - if (property->isQObject()) - fastgetter = FAST_GETTER_FUNCTION(property, QObject*); - else if (property->propType == QMetaType::Int || property->isEnum()) - fastgetter = FAST_GETTER_FUNCTION(property, int); - else if (property->propType == QMetaType::Bool) - fastgetter = FAST_GETTER_FUNCTION(property, bool); - else if (property->propType == QMetaType::QString) - fastgetter = FAST_GETTER_FUNCTION(property, QString); - else if (property->propType == QMetaType::UInt) - fastgetter = FAST_GETTER_FUNCTION(property, uint); - else if (property->propType == QMetaType::Float) - fastgetter = FAST_GETTER_FUNCTION(property, float); - else if (property->propType == QMetaType::Double) - fastgetter = FAST_GETTER_FUNCTION(property, double); - - if (fastgetter) { - if (ft.IsEmpty()) { - ft = v8::FunctionTemplate::New(); - ft->InstanceTemplate()->SetFallbackPropertyHandler(QV8QObjectWrapper::Getter, - QV8QObjectWrapper::Setter, - QV8QObjectWrapper::Query, - 0, - QV8QObjectWrapper::Enumerator); - ft->InstanceTemplate()->SetHasExternalResource(true); - } - - v8::AccessorSetter fastsetter = FastValueSetter; - if (!property->isWritable()) - fastsetter = FastValueSetterReadOnly; - - // We wrap the raw QQmlPropertyData pointer here. This is safe as the - // pointer will remain valid at least as long as the lifetime of any QObject's of - // this type and the property accessor checks if the object is 0 (deleted) before - // dereferencing the pointer. - ft->InstanceTemplate()->SetAccessor(engine->toString(iter.key()), fastgetter, fastsetter, - v8::External::New(property)); - } - } - - if (ft.IsEmpty()) { - constructor = qPersistentNew<v8::Function>(engine->qobjectWrapper()->m_constructor); - } else { - ft->InstanceTemplate()->SetFallbackPropertyHandler(QV8QObjectWrapper::Getter, - QV8QObjectWrapper::Setter, - QV8QObjectWrapper::Query, - 0, - QV8QObjectWrapper::Enumerator); - ft->InstanceTemplate()->SetHasExternalResource(true); - constructor = qPersistentNew<v8::Function>(ft->GetFunction()); - } - - QQmlCleanup::addToEngine(this->engine); - } - - v8::Local<v8::Object> result = constructor->NewInstance(); - QV8QObjectResource *r = new QV8QObjectResource(engine, object); - result->SetExternalResource(r); - return result; -} - -v8::Local<v8::Object> QV8QObjectWrapper::newQObject(QObject *object, QQmlData *ddata, QV8Engine *engine) -{ - v8::Local<v8::Object> rv; - - if (!ddata->propertyCache && engine->engine()) { - ddata->propertyCache = QQmlEnginePrivate::get(engine->engine())->cache(object); - if (ddata->propertyCache) ddata->propertyCache->addref(); - } - - if (ddata->propertyCache && ddata->propertyCache->qmlEngine() == engine->engine()) { - rv = ddata->propertyCache->newQObject(object, engine); - } else { - // XXX NewInstance() should be optimized - rv = m_constructor->NewInstance(); - QV8QObjectResource *r = new QV8QObjectResource(engine, object); - rv->SetExternalResource(r); - } - - return rv; -} - -/* -As V8 doesn't support an equality callback, for QObject's we have to return exactly the same -V8 handle for subsequent calls to newQObject for the same QObject. To do this we have a two -pronged strategy: - 1. If there is no current outstanding V8 handle to the QObject, we create one and store a - persistent handle in QQmlData::v8object. We mark the QV8QObjectWrapper that - "owns" this handle by setting the QQmlData::v8objectid to the id of this - QV8QObjectWrapper. - 2. If another QV8QObjectWrapper has create the handle in QQmlData::v8object we create - an entry in the m_taintedObject hash where we store the handle and mark the object as - "tainted" in the QQmlData::hasTaintedV8Object flag. -We have to mark the object as tainted to ensure that we search our m_taintedObject hash even -in the case that the original QV8QObjectWrapper owner of QQmlData::v8object has -released the handle. -*/ -v8::Handle<v8::Value> QV8QObjectWrapper::newQObject(QObject *object) -{ - if (QQmlData::wasDeleted(object)) - return v8::Null(); - - QQmlData *ddata = QQmlData::get(object, true); - if (!ddata) - return v8::Undefined(); - - if (ddata->v8objectid == m_id && !ddata->v8object.IsEmpty()) { - // We own the v8object - return v8::Local<v8::Object>::New(ddata->v8object); - } else if (ddata->v8object.IsEmpty() && - (ddata->v8objectid == m_id || // We own the QObject - ddata->v8objectid == 0 || // No one owns the QObject - !ddata->hasTaintedV8Object)) { // Someone else has used the QObject, but it isn't tainted - - v8::Local<v8::Object> rv = newQObject(object, ddata, m_engine); - ddata->v8object = qPersistentNew<v8::Object>(rv); - ddata->v8object.MakeWeak(this, WeakQObjectReferenceCallback); - ddata->v8objectid = m_id; - QV8QObjectResource *resource = v8_resource_check<QV8QObjectResource>(rv); - registerWeakQObjectReference(resource); - return rv; - - } else { - // If this object is tainted, we have to check to see if it is in our - // tainted object list - TaintedHash::Iterator iter = - ddata->hasTaintedV8Object?m_taintedObjects.find(object):m_taintedObjects.end(); - bool found = iter != m_taintedObjects.end(); - - // If our tainted handle doesn't exist or has been collected, and there isn't - // a handle in the ddata, we can assume ownership of the ddata->v8object - if ((!found || (*iter)->v8object.IsEmpty()) && ddata->v8object.IsEmpty()) { - v8::Local<v8::Object> rv = newQObject(object, ddata, m_engine); - ddata->v8object = qPersistentNew<v8::Object>(rv); - ddata->v8object.MakeWeak(this, WeakQObjectReferenceCallback); - ddata->v8objectid = m_id; - QV8QObjectResource *resource = v8_resource_check<QV8QObjectResource>(rv); - registerWeakQObjectReference(resource); - - if (found) { - delete (*iter); - m_taintedObjects.erase(iter); - } - - return rv; - } else if (!found) { - QV8QObjectInstance *instance = new QV8QObjectInstance(object, this); - iter = m_taintedObjects.insert(object, instance); - ddata->hasTaintedV8Object = true; - } - - if ((*iter)->v8object.IsEmpty()) { - v8::Local<v8::Object> rv = newQObject(object, ddata, m_engine); - (*iter)->v8object = qPersistentNew<v8::Object>(rv); - (*iter)->v8object.MakeWeak((*iter), WeakQObjectInstanceCallback); - } - - return v8::Local<v8::Object>::New((*iter)->v8object); - } -} - -// returns true if the object's qqmldata v8object handle should -// be disposed by the caller, false if it should not be (due to -// creation status, etc). -bool QV8QObjectWrapper::deleteWeakQObject(QV8QObjectResource *resource, bool calledFromEngineDtor) -{ - QObject *object = resource->object; - if (object) { - QQmlData *ddata = QQmlData::get(object, false); - if (ddata) { - if (!calledFromEngineDtor && ddata->rootObjectInCreation) { - // if weak ref callback is triggered (by gc) for a root object - // prior to completion of creation, we should NOT delete it. - return false; - } - - ddata->v8object.Clear(); - if (!object->parent() && !ddata->indestructible) { - // This object is notionally destroyed now - if (ddata->ownContext && ddata->context) - ddata->context->emitDestruction(); - ddata->isQueuedForDeletion = true; - if (calledFromEngineDtor) - delete object; - else - object->deleteLater(); - } - } - } - - return true; -} - -QPair<QObject *, int> QV8QObjectWrapper::ExtractQtSignal(QV8Engine *engine, v8::Handle<v8::Object> object) -{ - if (object->IsFunction()) - return ExtractQtMethod(engine, v8::Handle<v8::Function>::Cast(object)); - - if (QV8SignalHandlerResource *resource = v8_resource_cast<QV8SignalHandlerResource>(object)) - return qMakePair(resource->object.data(), resource->index); - - return qMakePair((QObject *)0, -1); -} - -QPair<QObject *, int> QV8QObjectWrapper::ExtractQtMethod(QV8Engine *engine, v8::Handle<v8::Function> function) -{ - v8::ScriptOrigin origin = function->GetScriptOrigin(); - if (origin.ResourceName()->StrictEquals(engine->qobjectWrapper()->m_hiddenObject)) { - - // This is one of our special QObject method wrappers - v8::Handle<v8::Value> args[] = { engine->qobjectWrapper()->m_hiddenObject }; - v8::Local<v8::Value> data = function->Call(engine->global(), 1, args); - - if (data->IsArray()) { - v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast(data); - return qMakePair(engine->toQObject(array->Get(0)), array->Get(1)->Int32Value()); - } - - // In theory this can't fall through, but I suppose V8 might run out of memory or something - } - - return qMakePair((QObject *)0, -1); -} - -class QV8QObjectConnectionList : public QObject, public QQmlGuard<QObject> -{ -public: - QV8QObjectConnectionList(QObject *object, QV8Engine *engine); - ~QV8QObjectConnectionList(); - - struct Connection { - Connection() - : needsDestroy(false) {} - Connection(const Connection &other) - : thisObject(other.thisObject), function(other.function), needsDestroy(false) {} - Connection &operator=(const Connection &other) { - thisObject = other.thisObject; - function = other.function; - needsDestroy = other.needsDestroy; - return *this; - } - - v8::Persistent<v8::Object> thisObject; - v8::Persistent<v8::Function> function; - - void dispose() { - qPersistentDispose(thisObject); - qPersistentDispose(function); - } - - bool needsDestroy; - }; - - struct ConnectionList : public QList<Connection> { - ConnectionList() : connectionsInUse(0), connectionsNeedClean(false) {} - int connectionsInUse; - bool connectionsNeedClean; - }; - - QV8Engine *engine; - - typedef QHash<int, ConnectionList> SlotHash; - SlotHash slotHash; - bool needsDestroy; - int inUse; - - virtual void objectDestroyed(QObject *); - virtual int qt_metacall(QMetaObject::Call, int, void **); -}; - -QV8QObjectConnectionList::QV8QObjectConnectionList(QObject *object, QV8Engine *engine) -: QQmlGuard<QObject>(object), engine(engine), needsDestroy(false), inUse(0) -{ -} - -QV8QObjectConnectionList::~QV8QObjectConnectionList() -{ - for (SlotHash::Iterator iter = slotHash.begin(); iter != slotHash.end(); ++iter) { - QList<Connection> &connections = *iter; - for (int ii = 0; ii < connections.count(); ++ii) { - qPersistentDispose(connections[ii].thisObject); - qPersistentDispose(connections[ii].function); - } - } - slotHash.clear(); -} - -void QV8QObjectConnectionList::objectDestroyed(QObject *object) -{ - engine->qobjectWrapper()->m_connections.remove(object); - - if (inUse) - needsDestroy = true; - else - delete this; -} - -int QV8QObjectConnectionList::qt_metacall(QMetaObject::Call method, int index, void **metaArgs) -{ - if (method == QMetaObject::InvokeMetaMethod) { - SlotHash::Iterator iter = slotHash.find(index); - if (iter == slotHash.end()) - return -1; - ConnectionList &connectionList = *iter; - if (connectionList.isEmpty()) - return -1; - - inUse++; - - connectionList.connectionsInUse++; - - QList<Connection> connections = connectionList; - - QVarLengthArray<int, 9> dummy; - int *argsTypes = QQmlPropertyCache::methodParameterTypes(data(), index, dummy, 0); - - v8::HandleScope handle_scope; - v8::Context::Scope scope(engine->context()); - - int argCount = argsTypes?argsTypes[0]:0; - QVarLengthArray<v8::Handle<v8::Value>, 9> args(argCount); - - for (int ii = 0; ii < argCount; ++ii) { - int type = argsTypes[ii + 1]; - if (type == qMetaTypeId<QVariant>()) { - args[ii] = engine->fromVariant(*((QVariant *)metaArgs[ii + 1])); - } else { - args[ii] = engine->fromVariant(QVariant(type, metaArgs[ii + 1])); - } - } - - for (int ii = 0; ii < connections.count(); ++ii) { - Connection &connection = connections[ii]; - if (connection.needsDestroy) - continue; - - v8::TryCatch try_catch; - if (connection.thisObject.IsEmpty()) { - connection.function->Call(engine->global(), argCount, args.data()); - } else { - connection.function->Call(connection.thisObject, argCount, args.data()); - } - - if (try_catch.HasCaught()) { - QQmlError error; - error.setDescription(QString(QLatin1String("Unknown exception occurred during evaluation of connected function: %1")).arg(engine->toString(connection.function->GetName()))); - v8::Local<v8::Message> message = try_catch.Message(); - if (!message.IsEmpty()) - QQmlExpressionPrivate::exceptionToError(message, error); - QQmlEnginePrivate::get(engine->engine())->warning(error); - } - } - - connectionList.connectionsInUse--; - if (connectionList.connectionsInUse == 0 && connectionList.connectionsNeedClean) { - for (QList<Connection>::Iterator iter = connectionList.begin(); - iter != connectionList.end(); ) { - if (iter->needsDestroy) { - iter->dispose(); - iter = connectionList.erase(iter); - } else { - ++iter; - } - } - } - - inUse--; - if (inUse == 0 && needsDestroy) - delete this; - } - - return -1; -} - -v8::Handle<v8::Value> QV8QObjectWrapper::Connect(const v8::Arguments &args) -{ - if (args.Length() == 0) - V8THROW_ERROR("Function.prototype.connect: no arguments given"); - - QV8Engine *engine = V8ENGINE(); - - QPair<QObject *, int> signalInfo = ExtractQtSignal(engine, args.This()); - QObject *signalObject = signalInfo.first; - int signalIndex = signalInfo.second; - - if (signalIndex < 0) - V8THROW_ERROR("Function.prototype.connect: this object is not a signal"); - - if (!signalObject) - V8THROW_ERROR("Function.prototype.connect: cannot connect to deleted QObject"); - - if (signalObject->metaObject()->method(signalIndex).methodType() != QMetaMethod::Signal) - V8THROW_ERROR("Function.prototype.connect: this object is not a signal"); - - v8::Local<v8::Value> functionValue; - v8::Local<v8::Value> functionThisValue; - - if (args.Length() == 1) { - functionValue = args[0]; - } else { - functionThisValue = args[0]; - functionValue = args[1]; - } - - if (!functionValue->IsFunction()) - V8THROW_ERROR("Function.prototype.connect: target is not a function"); - - if (!functionThisValue.IsEmpty() && !functionThisValue->IsObject()) - V8THROW_ERROR("Function.prototype.connect: target this is not an object"); - - QV8QObjectWrapper *qobjectWrapper = engine->qobjectWrapper(); - QHash<QObject *, QV8QObjectConnectionList *> &connections = qobjectWrapper->m_connections; - QHash<QObject *, QV8QObjectConnectionList *>::Iterator iter = connections.find(signalObject); - if (iter == connections.end()) - iter = connections.insert(signalObject, new QV8QObjectConnectionList(signalObject, engine)); - - QV8QObjectConnectionList *connectionList = *iter; - QV8QObjectConnectionList::SlotHash::Iterator slotIter = connectionList->slotHash.find(signalIndex); - if (slotIter == connectionList->slotHash.end()) { - slotIter = connectionList->slotHash.insert(signalIndex, QV8QObjectConnectionList::ConnectionList()); - QMetaObject::connect(signalObject, signalIndex, connectionList, signalIndex); - } - - QV8QObjectConnectionList::Connection connection; - if (!functionThisValue.IsEmpty()) - connection.thisObject = qPersistentNew<v8::Object>(functionThisValue->ToObject()); - connection.function = qPersistentNew<v8::Function>(v8::Handle<v8::Function>::Cast(functionValue)); - - slotIter->append(connection); - - return v8::Undefined(); -} - -v8::Handle<v8::Value> QV8QObjectWrapper::Disconnect(const v8::Arguments &args) -{ - if (args.Length() == 0) - V8THROW_ERROR("Function.prototype.disconnect: no arguments given"); - - QV8Engine *engine = V8ENGINE(); - - QPair<QObject *, int> signalInfo = ExtractQtSignal(engine, args.This()); - QObject *signalObject = signalInfo.first; - int signalIndex = signalInfo.second; - - if (signalIndex == -1) - V8THROW_ERROR("Function.prototype.disconnect: this object is not a signal"); - - if (!signalObject) - V8THROW_ERROR("Function.prototype.disconnect: cannot disconnect from deleted QObject"); - - if (signalIndex < 0 || signalObject->metaObject()->method(signalIndex).methodType() != QMetaMethod::Signal) - V8THROW_ERROR("Function.prototype.disconnect: this object is not a signal"); - - v8::Local<v8::Value> functionValue; - v8::Local<v8::Value> functionThisValue; - - if (args.Length() == 1) { - functionValue = args[0]; - } else { - functionThisValue = args[0]; - functionValue = args[1]; - } - - if (!functionValue->IsFunction()) - V8THROW_ERROR("Function.prototype.disconnect: target is not a function"); - - if (!functionThisValue.IsEmpty() && !functionThisValue->IsObject()) - V8THROW_ERROR("Function.prototype.disconnect: target this is not an object"); - - QV8QObjectWrapper *qobjectWrapper = engine->qobjectWrapper(); - QHash<QObject *, QV8QObjectConnectionList *> &connectionsList = qobjectWrapper->m_connections; - QHash<QObject *, QV8QObjectConnectionList *>::Iterator iter = connectionsList.find(signalObject); - if (iter == connectionsList.end()) - return v8::Undefined(); // Nothing to disconnect from - - QV8QObjectConnectionList *connectionList = *iter; - QV8QObjectConnectionList::SlotHash::Iterator slotIter = connectionList->slotHash.find(signalIndex); - if (slotIter == connectionList->slotHash.end()) - return v8::Undefined(); // Nothing to disconnect from - - QV8QObjectConnectionList::ConnectionList &connections = *slotIter; - - v8::Local<v8::Function> function = v8::Local<v8::Function>::Cast(functionValue); - QPair<QObject *, int> functionData = ExtractQtMethod(engine, function); - - if (functionData.second != -1) { - // This is a QObject function wrapper - for (int ii = 0; ii < connections.count(); ++ii) { - QV8QObjectConnectionList::Connection &connection = connections[ii]; - - if (connection.thisObject.IsEmpty() == functionThisValue.IsEmpty() && - (connection.thisObject.IsEmpty() || connection.thisObject->StrictEquals(functionThisValue))) { - - QPair<QObject *, int> connectedFunctionData = ExtractQtMethod(engine, connection.function); - if (connectedFunctionData == functionData) { - // Match! - if (connections.connectionsInUse) { - connection.needsDestroy = true; - connections.connectionsNeedClean = true; - } else { - connection.dispose(); - connections.removeAt(ii); - } - return v8::Undefined(); - } - } - } - - } else { - // This is a normal JS function - for (int ii = 0; ii < connections.count(); ++ii) { - QV8QObjectConnectionList::Connection &connection = connections[ii]; - if (connection.function->StrictEquals(function) && - connection.thisObject.IsEmpty() == functionThisValue.IsEmpty() && - (connection.thisObject.IsEmpty() || connection.thisObject->StrictEquals(functionThisValue))) { - // Match! - if (connections.connectionsInUse) { - connection.needsDestroy = true; - connections.connectionsNeedClean = true; - } else { - connection.dispose(); - connections.removeAt(ii); - } - return v8::Undefined(); - } - } - } - - return v8::Undefined(); -} - -/*! - \fn v8::Handle<v8::Value> QV8QObjectWrapper::getProperty(QObject *object, const QHashedV8String &property, QV8QObjectWrapper::RevisionMode revisionMode) - - Get the \a property of \a object. Returns an empty handle if the property doesn't exist. - - Only searches for real properties of \a object (including methods), not attached properties etc. -*/ - -/* - \fn bool QV8QObjectWrapper::setProperty(QObject *object, const QHashedV8String &property, v8::Handle<v8::Value> value, RevisionMode revisionMode) - - Set the \a property of \a object to \a value. - - Returns true if the property was "set" - even if this results in an exception being thrown - - and false if the object has no such property. - - Only searches for real properties of \a object (including methods), not attached properties etc. -*/ - -namespace { -struct CallArgs -{ - CallArgs(int length, v8::Handle<v8::Object> *args) : _length(length), _args(args) {} - int Length() const { return _length; } - v8::Local<v8::Value> operator[](int idx) { return (*_args)->Get(idx); } - -private: - int _length; - v8::Handle<v8::Object> *_args; -}; -} - -static v8::Handle<v8::Value> CallMethod(QObject *object, int index, int returnType, int argCount, - int *argTypes, QV8Engine *engine, CallArgs &callArgs) -{ - if (argCount > 0) { - - // Special handling is required for value types. - // We need to save the current value in a temporary, - // and reapply it after converting all arguments. - // This avoids the "overwriting copy-value-type-value" - // problem during Q_INVOKABLE function invocation. - QQmlValueType *valueTypeObject = qobject_cast<QQmlValueType*>(object); - QVariant valueTypeValue; - if (valueTypeObject) - valueTypeValue = valueTypeObject->value(); - - // Convert all arguments. - QVarLengthArray<CallArgument, 9> args(argCount + 1); - args[0].initAsType(returnType); - for (int ii = 0; ii < argCount; ++ii) - args[ii + 1].fromValue(argTypes[ii], engine, callArgs[ii]); - QVarLengthArray<void *, 9> argData(args.count()); - for (int ii = 0; ii < args.count(); ++ii) - argData[ii] = args[ii].dataPtr(); - - // Reinstate saved value type object value if required. - if (valueTypeObject) - valueTypeObject->setValue(valueTypeValue); - - QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, index, argData.data()); - - return args[0].toValue(engine); - - } else if (returnType != QMetaType::Void) { - - CallArgument arg; - arg.initAsType(returnType); - - void *args[] = { arg.dataPtr() }; - - QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, index, args); - - return arg.toValue(engine); - - } else { - - void *args[] = { 0 }; - QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, index, args); - return v8::Undefined(); - - } -} - -/*! - Returns the match score for converting \a actual to be of type \a conversionType. A - zero score means "perfect match" whereas a higher score is worse. - - The conversion table is copied out of the \l QScript::callQtMethod() - function. -*/ -static int MatchScore(v8::Handle<v8::Value> actual, int conversionType) -{ - if (actual->IsNumber()) { - switch (conversionType) { - case QMetaType::Double: - return 0; - case QMetaType::Float: - return 1; - case QMetaType::LongLong: - case QMetaType::ULongLong: - return 2; - case QMetaType::Long: - case QMetaType::ULong: - return 3; - case QMetaType::Int: - case QMetaType::UInt: - return 4; - case QMetaType::Short: - case QMetaType::UShort: - return 5; - break; - case QMetaType::Char: - case QMetaType::UChar: - return 6; - case QMetaType::QJsonValue: - return 5; - default: - return 10; - } - } else if (actual->IsString()) { - switch (conversionType) { - case QMetaType::QString: - return 0; - case QMetaType::QJsonValue: - return 5; - default: - return 10; - } - } else if (actual->IsBoolean()) { - switch (conversionType) { - case QMetaType::Bool: - return 0; - case QMetaType::QJsonValue: - return 5; - default: - return 10; - } - } else if (actual->IsDate()) { - switch (conversionType) { - case QMetaType::QDateTime: - return 0; - case QMetaType::QDate: - return 1; - case QMetaType::QTime: - return 2; - default: - return 10; - } - } else if (actual->IsRegExp()) { - switch (conversionType) { - case QMetaType::QRegExp: - return 0; - default: - return 10; - } - } else if (actual->IsArray()) { - switch (conversionType) { - case QMetaType::QJsonArray: - return 3; - case QMetaType::QStringList: - case QMetaType::QVariantList: - return 5; - case QMetaType::QVector4D: - case QMetaType::QMatrix4x4: - return 6; - case QMetaType::QVector3D: - return 7; - default: - return 10; - } - } else if (actual->IsNull()) { - switch (conversionType) { - case QMetaType::VoidStar: - case QMetaType::QObjectStar: - case QMetaType::QJsonValue: - return 0; - default: { - const char *typeName = QMetaType::typeName(conversionType); - if (typeName && typeName[strlen(typeName) - 1] == '*') - return 0; - else - return 10; - } - } - } else if (actual->IsObject()) { - v8::Handle<v8::Object> obj = v8::Handle<v8::Object>::Cast(actual); - - QV8ObjectResource *r = static_cast<QV8ObjectResource *>(obj->GetExternalResource()); - if (r && r->resourceType() == QV8ObjectResource::QObjectType) { - switch (conversionType) { - case QMetaType::QObjectStar: - return 0; - default: - return 10; - } - } else if (r && r->resourceType() == QV8ObjectResource::VariantType) { - if (conversionType == qMetaTypeId<QVariant>()) - return 0; - else if (r->engine->toVariant(actual, -1).userType() == conversionType) - return 0; - else - return 10; - } else if (r && r->resourceType() == QV8ObjectResource::ValueTypeType) { - if (r->engine->toVariant(actual, -1).userType() == conversionType) - return 0; - return 10; - } else if (conversionType == QMetaType::QJsonObject) { - return 5; - } else { - return 10; - } - - } else { - return 10; - } -} - -static inline int QMetaObject_methods(const QMetaObject *metaObject) -{ - struct Private - { - int revision; - int className; - int classInfoCount, classInfoData; - int methodCount, methodData; - }; - - return reinterpret_cast<const Private *>(metaObject->d.data)->methodCount; -} - -/*! -Returns the next related method, if one, or 0. -*/ -static const QQmlPropertyData * RelatedMethod(QObject *object, - const QQmlPropertyData *current, - QQmlPropertyData &dummy) -{ - QQmlPropertyCache *cache = QQmlData::get(object)->propertyCache; - if (!current->isOverload()) - return 0; - - Q_ASSERT(!current->overrideIndexIsProperty); - - if (cache) { - return cache->method(current->overrideIndex); - } else { - const QMetaObject *mo = object->metaObject(); - int methodOffset = mo->methodCount() - QMetaObject_methods(mo); - - while (methodOffset > current->overrideIndex) { - mo = mo->superClass(); - methodOffset -= QMetaObject_methods(mo); - } - - QMetaMethod method = mo->method(current->overrideIndex); - dummy.load(method); - - // Look for overloaded methods - QByteArray methodName = method.name(); - for (int ii = current->overrideIndex - 1; ii >= methodOffset; --ii) { - if (methodName == mo->method(ii).name()) { - dummy.setFlags(dummy.getFlags() | QQmlPropertyData::IsOverload); - dummy.overrideIndexIsProperty = 0; - dummy.overrideIndex = ii; - return &dummy; - } - } - - return &dummy; - } -} - -static v8::Handle<v8::Value> CallPrecise(QObject *object, const QQmlPropertyData &data, - QV8Engine *engine, CallArgs &callArgs) -{ - QByteArray unknownTypeError; - - int returnType = QQmlPropertyCache::methodReturnType(object, data, &unknownTypeError); - - if (returnType == QMetaType::UnknownType) { - QString typeName = QString::fromLatin1(unknownTypeError); - QString error = QString::fromLatin1("Unknown method return type: %1").arg(typeName); - v8::ThrowException(v8::Exception::Error(engine->toString(error))); - return v8::Handle<v8::Value>(); - } - - if (data.hasArguments()) { - - int *args = 0; - QVarLengthArray<int, 9> dummy; - - args = QQmlPropertyCache::methodParameterTypes(object, data.coreIndex, dummy, - &unknownTypeError); - - if (!args) { - QString typeName = QString::fromLatin1(unknownTypeError); - QString error = QString::fromLatin1("Unknown method parameter type: %1").arg(typeName); - v8::ThrowException(v8::Exception::Error(engine->toString(error))); - return v8::Handle<v8::Value>(); - } - - if (args[0] > callArgs.Length()) { - QString error = QLatin1String("Insufficient arguments"); - v8::ThrowException(v8::Exception::Error(engine->toString(error))); - return v8::Handle<v8::Value>(); - } - - return CallMethod(object, data.coreIndex, returnType, args[0], args + 1, engine, callArgs); - - } else { - - return CallMethod(object, data.coreIndex, returnType, 0, 0, engine, callArgs); - - } -} - -/*! -Resolve the overloaded method to call. The algorithm works conceptually like this: - 1. Resolve the set of overloads it is *possible* to call. - Impossible overloads include those that have too many parameters or have parameters - of unknown type. - 2. Filter the set of overloads to only contain those with the closest number of - parameters. - For example, if we are called with 3 parameters and there are 2 overloads that - take 2 parameters and one that takes 3, eliminate the 2 parameter overloads. - 3. Find the best remaining overload based on its match score. - If two or more overloads have the same match score, call the last one. The match - score is constructed by adding the matchScore() result for each of the parameters. -*/ -static v8::Handle<v8::Value> CallOverloaded(QObject *object, const QQmlPropertyData &data, - QV8Engine *engine, CallArgs &callArgs) -{ - int argumentCount = callArgs.Length(); - - const QQmlPropertyData *best = 0; - int bestParameterScore = INT_MAX; - int bestMatchScore = INT_MAX; - - // Special handling is required for value types. - // We need to save the current value in a temporary, - // and reapply it after converting all arguments. - // This avoids the "overwriting copy-value-type-value" - // problem during Q_INVOKABLE function invocation. - QQmlValueType *valueTypeObject = qobject_cast<QQmlValueType*>(object); - QVariant valueTypeValue; - if (valueTypeObject) - valueTypeValue = valueTypeObject->value(); - - QQmlPropertyData dummy; - const QQmlPropertyData *attempt = &data; - - do { - QVarLengthArray<int, 9> dummy; - int methodArgumentCount = 0; - int *methodArgTypes = 0; - if (attempt->hasArguments()) { - typedef QQmlPropertyCache PC; - int *args = PC::methodParameterTypes(object, attempt->coreIndex, dummy, 0); - if (!args) // Must be an unknown argument - continue; - - methodArgumentCount = args[0]; - methodArgTypes = args + 1; - } - - if (methodArgumentCount > argumentCount) - continue; // We don't have sufficient arguments to call this method - - int methodParameterScore = argumentCount - methodArgumentCount; - if (methodParameterScore > bestParameterScore) - continue; // We already have a better option - - int methodMatchScore = 0; - for (int ii = 0; ii < methodArgumentCount; ++ii) - methodMatchScore += MatchScore(callArgs[ii], methodArgTypes[ii]); - - if (bestParameterScore > methodParameterScore || bestMatchScore > methodMatchScore) { - best = attempt; - bestParameterScore = methodParameterScore; - bestMatchScore = methodMatchScore; - } - - if (bestParameterScore == 0 && bestMatchScore == 0) - break; // We can't get better than that - - } while((attempt = RelatedMethod(object, attempt, dummy)) != 0); - - if (best) { - if (valueTypeObject) - valueTypeObject->setValue(valueTypeValue); - return CallPrecise(object, *best, engine, callArgs); - } else { - QString error = QLatin1String("Unable to determine callable overload. Candidates are:"); - const QQmlPropertyData *candidate = &data; - while (candidate) { - error += QLatin1String("\n ") + - QString::fromUtf8(object->metaObject()->method(candidate->coreIndex).methodSignature().constData()); - candidate = RelatedMethod(object, candidate, dummy); - } - - v8::ThrowException(v8::Exception::Error(engine->toString(error))); - return v8::Handle<v8::Value>(); - } -} - -static v8::Handle<v8::Value> ToString(QV8Engine *engine, QObject *object, int, v8::Handle<v8::Object>) -{ - QString result; - if (object) { - QString objectName = object->objectName(); - - result += QString::fromUtf8(object->metaObject()->className()); - result += QLatin1String("(0x"); - result += QString::number((quintptr)object,16); - - if (!objectName.isEmpty()) { - result += QLatin1String(", \""); - result += objectName; - result += QLatin1Char('\"'); - } - - result += QLatin1Char(')'); - } else { - result = QLatin1String("null"); - } - - return engine->toString(result); -} - -static v8::Handle<v8::Value> Destroy(QV8Engine *, QObject *object, int argCount, v8::Handle<v8::Object> args) -{ - QQmlData *ddata = QQmlData::get(object, false); - if (!ddata || ddata->indestructible || ddata->rootObjectInCreation) { - const char *error = "Invalid attempt to destroy() an indestructible object"; - v8::ThrowException(v8::Exception::Error(v8::String::New(error))); - return v8::Undefined(); - } - - int delay = 0; - if (argCount > 0) - delay = args->Get(0)->Uint32Value(); - - if (delay > 0) - QTimer::singleShot(delay, object, SLOT(deleteLater())); - else - object->deleteLater(); - - return v8::Undefined(); -} - -v8::Handle<v8::Value> QV8QObjectWrapper::Invoke(const v8::Arguments &args) -{ - // object, index, qmlglobal, argCount, args - Q_ASSERT(args.Length() == 5); - Q_ASSERT(args[0]->IsObject()); - - QV8QObjectResource *resource = v8_resource_cast<QV8QObjectResource>(args[0]->ToObject()); - - if (!resource) - return v8::Undefined(); - - int argCount = args[3]->Int32Value(); - v8::Handle<v8::Object> arguments = v8::Handle<v8::Object>::Cast(args[4]); - - // Special hack to return info about this closure. - if (argCount == 1 && arguments->Get(0)->StrictEquals(resource->engine->qobjectWrapper()->m_hiddenObject)) { - v8::Local<v8::Array> data = v8::Array::New(2); - data->Set(0, args[0]); - data->Set(1, args[1]); - return data; - } - - QObject *object = resource->object; - int index = args[1]->Int32Value(); - - if (!object) - return v8::Undefined(); - - if (index < 0) { - // Builtin functions - if (index == QOBJECT_TOSTRING_INDEX) { - return ToString(resource->engine, object, argCount, arguments); - } else if (index == QOBJECT_DESTROY_INDEX) { - return Destroy(resource->engine, object, argCount, arguments); - } else { - return v8::Undefined(); - } - } - - QQmlPropertyData method; - - if (QQmlData *ddata = static_cast<QQmlData *>(QObjectPrivate::get(object)->declarativeData)) { - if (ddata->propertyCache) { - QQmlPropertyData *d = ddata->propertyCache->method(index); - if (!d) - return v8::Undefined(); - method = *d; - } - } - - if (method.coreIndex == -1) { - method.load(object->metaObject()->method(index)); - - if (method.coreIndex == -1) - return v8::Undefined(); - } - - if (method.isV8Function()) { - v8::Handle<v8::Value> rv; - v8::Handle<v8::Object> qmlglobal = args[2]->ToObject(); - - QQmlV8Function func(argCount, arguments, rv, qmlglobal, - resource->engine->contextWrapper()->context(qmlglobal), - resource->engine); - QQmlV8Function *funcptr = &func; - - void *args[] = { 0, &funcptr }; - QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, method.coreIndex, args); - - if (rv.IsEmpty()) return v8::Undefined(); - return rv; - } - - CallArgs callArgs(argCount, &arguments); - if (!method.isOverload()) { - return CallPrecise(object, method, resource->engine, callArgs); - } else { - return CallOverloaded(object, method, resource->engine, callArgs); - } -} - -CallArgument::CallArgument() -: type(QVariant::Invalid) -{ -} - -CallArgument::~CallArgument() -{ - cleanup(); -} - -void CallArgument::cleanup() -{ - if (type == QMetaType::QString) { - qstringPtr->~QString(); - } else if (type == -1 || type == QMetaType::QVariant) { - qvariantPtr->~QVariant(); - } else if (type == qMetaTypeId<QJSValue>()) { - qjsValuePtr->~QJSValue(); - } else if (type == qMetaTypeId<QList<QObject *> >()) { - qlistPtr->~QList<QObject *>(); - } else if (type == QMetaType::QJsonArray) { - jsonArrayPtr->~QJsonArray(); - } else if (type == QMetaType::QJsonObject) { - jsonObjectPtr->~QJsonObject(); - } else if (type == QMetaType::QJsonValue) { - jsonValuePtr->~QJsonValue(); - } -} - -void *CallArgument::dataPtr() -{ - if (type == -1) - return qvariantPtr->data(); - else - return (void *)&allocData; -} - -void CallArgument::initAsType(int callType) -{ - if (type != 0) { cleanup(); type = 0; } - if (callType == QMetaType::UnknownType) return; - - if (callType == qMetaTypeId<QJSValue>()) { - qjsValuePtr = new (&allocData) QJSValue(); - type = callType; - } else if (callType == QMetaType::Int || - callType == QMetaType::UInt || - callType == QMetaType::Bool || - callType == QMetaType::Double || - callType == QMetaType::Float) { - type = callType; - } else if (callType == QMetaType::QObjectStar) { - qobjectPtr = 0; - type = callType; - } else if (callType == QMetaType::QString) { - qstringPtr = new (&allocData) QString(); - type = callType; - } else if (callType == QMetaType::QVariant) { - type = callType; - qvariantPtr = new (&allocData) QVariant(); - } else if (callType == qMetaTypeId<QList<QObject *> >()) { - type = callType; - qlistPtr = new (&allocData) QList<QObject *>(); - } else if (callType == qMetaTypeId<QQmlV8Handle>()) { - type = callType; - handlePtr = new (&allocData) QQmlV8Handle; - } else if (callType == QMetaType::QJsonArray) { - type = callType; - jsonArrayPtr = new (&allocData) QJsonArray(); - } else if (callType == QMetaType::QJsonObject) { - type = callType; - jsonObjectPtr = new (&allocData) QJsonObject(); - } else if (callType == QMetaType::QJsonValue) { - type = callType; - jsonValuePtr = new (&allocData) QJsonValue(); - } else if (callType == QMetaType::Void) { - type = -1; - qvariantPtr = new (&allocData) QVariant(); - } else { - type = -1; - qvariantPtr = new (&allocData) QVariant(callType, (void *)0); - } -} - -void CallArgument::fromValue(int callType, QV8Engine *engine, v8::Handle<v8::Value> value) -{ - if (type != 0) { cleanup(); type = 0; } - - if (callType == qMetaTypeId<QJSValue>()) { - qjsValuePtr = new (&allocData) QJSValue(QJSValuePrivate::get(new QJSValuePrivate(engine, value))); - type = qMetaTypeId<QJSValue>(); - } else if (callType == QMetaType::Int) { - intValue = quint32(value->Int32Value()); - type = callType; - } else if (callType == QMetaType::UInt) { - intValue = quint32(value->Uint32Value()); - type = callType; - } else if (callType == QMetaType::Bool) { - boolValue = value->BooleanValue(); - type = callType; - } else if (callType == QMetaType::Double) { - doubleValue = double(value->NumberValue()); - type = callType; - } else if (callType == QMetaType::Float) { - floatValue = float(value->NumberValue()); - type = callType; - } else if (callType == QMetaType::QString) { - if (value->IsNull() || value->IsUndefined()) - qstringPtr = new (&allocData) QString(); - else - qstringPtr = new (&allocData) QString(engine->toString(value->ToString())); - type = callType; - } else if (callType == QMetaType::QObjectStar) { - qobjectPtr = engine->toQObject(value); - type = callType; - } else if (callType == qMetaTypeId<QVariant>()) { - qvariantPtr = new (&allocData) QVariant(engine->toVariant(value, -1)); - type = callType; - } else if (callType == qMetaTypeId<QList<QObject*> >()) { - qlistPtr = new (&allocData) QList<QObject *>(); - if (value->IsArray()) { - v8::Handle<v8::Array> array = v8::Handle<v8::Array>::Cast(value); - uint32_t length = array->Length(); - for (uint32_t ii = 0; ii < length; ++ii) - qlistPtr->append(engine->toQObject(array->Get(ii))); - } else { - qlistPtr->append(engine->toQObject(value)); - } - type = callType; - } else if (callType == qMetaTypeId<QQmlV8Handle>()) { - handlePtr = new (&allocData) QQmlV8Handle(QQmlV8Handle::fromHandle(value)); - type = callType; - } else if (callType == QMetaType::QJsonArray) { - jsonArrayPtr = new (&allocData) QJsonArray(engine->jsonArrayFromJS(value)); - type = callType; - } else if (callType == QMetaType::QJsonObject) { - jsonObjectPtr = new (&allocData) QJsonObject(engine->jsonObjectFromJS(value)); - type = callType; - } else if (callType == QMetaType::QJsonValue) { - jsonValuePtr = new (&allocData) QJsonValue(engine->jsonValueFromJS(value)); - type = callType; - } else if (callType == QMetaType::Void) { - *qvariantPtr = QVariant(); - } else { - qvariantPtr = new (&allocData) QVariant(); - type = -1; - - QQmlEnginePrivate *ep = engine->engine() ? QQmlEnginePrivate::get(engine->engine()) : 0; - QVariant v = engine->toVariant(value, -1); // why -1 instead of callType? - - if (v.userType() == callType) { - *qvariantPtr = v; - } else if (v.canConvert(callType)) { - *qvariantPtr = v; - qvariantPtr->convert(callType); - } else if (engine->sequenceWrapper()->isSequenceType(callType) && v.userType() == qMetaTypeId<QVariantList>()) { - // convert the JS array to a sequence of the correct type. - QVariant seqV = engine->toVariant(value, callType); - *qvariantPtr = seqV; - } else { - QQmlMetaObject mo = ep ? ep->rawMetaObjectForType(callType) : QQmlMetaObject(); - if (!mo.isNull()) { - QObject *obj = ep->toQObject(v); - - if (obj != 0 && !QQmlMetaObject::canConvert(obj, mo)) - obj = 0; - - *qvariantPtr = QVariant(callType, &obj); - } else { - *qvariantPtr = QVariant(callType, (void *)0); - } - } - } -} - -v8::Handle<v8::Value> CallArgument::toValue(QV8Engine *engine) -{ - if (type == qMetaTypeId<QJSValue>()) { - return QJSValuePrivate::get(*qjsValuePtr)->asV8Value(engine); - } else if (type == QMetaType::Int) { - return v8::Integer::New(int(intValue)); - } else if (type == QMetaType::UInt) { - return v8::Integer::NewFromUnsigned(intValue); - } else if (type == QMetaType::Bool) { - return v8::Boolean::New(boolValue); - } else if (type == QMetaType::Double) { - return v8::Number::New(doubleValue); - } else if (type == QMetaType::Float) { - return v8::Number::New(floatValue); - } else if (type == QMetaType::QString) { - return engine->toString(*qstringPtr); - } else if (type == QMetaType::QObjectStar) { - QObject *object = qobjectPtr; - if (object) - QQmlData::get(object, true)->setImplicitDestructible(); - return engine->newQObject(object); - } else if (type == qMetaTypeId<QList<QObject *> >()) { - // XXX Can this be made more by using Array as a prototype and implementing - // directly against QList<QObject*>? - QList<QObject *> &list = *qlistPtr; - v8::Local<v8::Array> array = v8::Array::New(list.count()); - for (int ii = 0; ii < list.count(); ++ii) - array->Set(ii, engine->newQObject(list.at(ii))); - return array; - } else if (type == qMetaTypeId<QQmlV8Handle>()) { - return handlePtr->toHandle(); - } else if (type == QMetaType::QJsonArray) { - return engine->jsonArrayToJS(*jsonArrayPtr); - } else if (type == QMetaType::QJsonObject) { - return engine->jsonObjectToJS(*jsonObjectPtr); - } else if (type == QMetaType::QJsonValue) { - return engine->jsonValueToJS(*jsonValuePtr); - } else if (type == -1 || type == qMetaTypeId<QVariant>()) { - QVariant value = *qvariantPtr; - v8::Handle<v8::Value> rv = engine->fromVariant(value); - if (QObject *object = engine->toQObject(rv)) - QQmlData::get(object, true)->setImplicitDestructible(); - return rv; - } else { - return v8::Undefined(); - } -} - -QT_END_NAMESPACE - diff --git a/src/qml/qml/v8/qv8qobjectwrapper_p.h b/src/qml/qml/v8/qv8qobjectwrapper_p.h deleted file mode 100644 index cbd6505846..0000000000 --- a/src/qml/qml/v8/qv8qobjectwrapper_p.h +++ /dev/null @@ -1,186 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QV8QOBJECTWRAPPER_P_H -#define QV8QOBJECTWRAPPER_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <QtCore/qglobal.h> -#include <QtCore/qmetatype.h> -#include <QtCore/qpair.h> -#include <QtCore/qhash.h> -#include <private/qv8_p.h> -#include <private/qhashedstring_p.h> -#include <private/qqmldata_p.h> -#include <private/qqmlpropertycache_p.h> -#include <private/qintrusivelist_p.h> -#include "qv8objectresource_p.h" - -QT_BEGIN_NAMESPACE - -class QObject; -class QV8Engine; -class QQmlData; -class QV8ObjectResource; -class QV8QObjectInstance; -class QV8QObjectConnectionList; -class QQmlPropertyCache; - -class QV8QObjectResource : public QV8ObjectResource -{ - V8_RESOURCE_TYPE(QObjectType) - -public: - QV8QObjectResource(QV8Engine *engine, QObject *object); - - QQmlGuard<QObject> object; - QIntrusiveListNode weakResource; -}; - -class Q_QML_PRIVATE_EXPORT QV8QObjectWrapper -{ -public: - QV8QObjectWrapper(); - ~QV8QObjectWrapper(); - - void init(QV8Engine *); - void destroy(); - - v8::Handle<v8::Value> newQObject(QObject *object); - bool isQObject(v8::Handle<v8::Object>); - QObject *toQObject(v8::Handle<v8::Object>); - static QObject *toQObject(QV8ObjectResource *); - - enum RevisionMode { IgnoreRevision, CheckRevision }; - inline v8::Handle<v8::Value> getProperty(QObject *, const QHashedV8String &, QQmlContextData *, RevisionMode); - inline bool setProperty(QObject *, const QHashedV8String &, QQmlContextData *, v8::Handle<v8::Value>, RevisionMode); - - void registerWeakQObjectReference(QV8QObjectResource *resource) - { - m_javaScriptOwnedWeakQObjects.insert(resource); - } - - void unregisterWeakQObjectReference(QV8QObjectResource *resource) - { - m_javaScriptOwnedWeakQObjects.remove(resource); - } - -private: - friend class QQmlPropertyCache; - friend class QV8QObjectConnectionList; - friend class QV8QObjectInstance; - - v8::Local<v8::Object> newQObject(QObject *, QQmlData *, QV8Engine *); - bool deleteWeakQObject(QV8QObjectResource *resource, bool calledFromEngineDtor = false); - static v8::Handle<v8::Value> GetProperty(QV8Engine *, QObject *, v8::Handle<v8::Value> *, - const QHashedV8String &, QQmlContextData *, QV8QObjectWrapper::RevisionMode); - static bool SetProperty(QV8Engine *, QObject *, const QHashedV8String &, QQmlContextData *, - v8::Handle<v8::Value>, QV8QObjectWrapper::RevisionMode); - static v8::Handle<v8::Value> Getter(v8::Local<v8::String> property, - const v8::AccessorInfo &info); - static v8::Handle<v8::Value> Setter(v8::Local<v8::String> property, - v8::Local<v8::Value> value, - const v8::AccessorInfo &info); - static v8::Handle<v8::Integer> Query(v8::Local<v8::String> property, - const v8::AccessorInfo &info); - static v8::Handle<v8::Array> Enumerator(const v8::AccessorInfo &info); - static v8::Handle<v8::Value> Connect(const v8::Arguments &args); - static v8::Handle<v8::Value> Disconnect(const v8::Arguments &args); - static v8::Handle<v8::Value> Invoke(const v8::Arguments &args); - static QPair<QObject *, int> ExtractQtMethod(QV8Engine *, v8::Handle<v8::Function>); - static QPair<QObject *, int> ExtractQtSignal(QV8Engine *, v8::Handle<v8::Object>); - static void WeakQObjectReferenceCallback(v8::Persistent<v8::Value> handle, void *wrapper); - - QV8Engine *m_engine; - quint32 m_id; - v8::Persistent<v8::Function> m_constructor; - v8::Persistent<v8::Function> m_methodConstructor; - v8::Persistent<v8::Function> m_signalHandlerConstructor; - v8::Persistent<v8::String> m_toStringSymbol; - v8::Persistent<v8::String> m_destroySymbol; - QHashedV8String m_toStringString; - QHashedV8String m_destroyString; - v8::Persistent<v8::Object> m_hiddenObject; - QHash<QObject *, QV8QObjectConnectionList *> m_connections; - typedef QHash<QObject *, QV8QObjectInstance *> TaintedHash; - TaintedHash m_taintedObjects; - QIntrusiveList<QV8QObjectResource, &QV8QObjectResource::weakResource> m_javaScriptOwnedWeakQObjects; -}; - -v8::Handle<v8::Value> QV8QObjectWrapper::getProperty(QObject *object, const QHashedV8String &string, - QQmlContextData *context, RevisionMode mode) -{ - QQmlData *dd = QQmlData::get(object, false); - if (!dd || !dd->propertyCache || m_toStringString == string || m_destroyString == string || - dd->propertyCache->property(string, object, context)) { - return GetProperty(m_engine, object, 0, string, context, mode); - } else { - return v8::Handle<v8::Value>(); - } -} - -bool QV8QObjectWrapper::setProperty(QObject *object, const QHashedV8String &string, - QQmlContextData *context, v8::Handle<v8::Value> value, RevisionMode mode) -{ - QQmlData *dd = QQmlData::get(object, false); - if (!dd || !dd->propertyCache || m_toStringString == string || m_destroyString == string || - dd->propertyCache->property(string, object, context)) { - return SetProperty(m_engine, object, string, context, value, mode); - } else { - return false; - } -} - -QT_END_NAMESPACE - -#endif // QV8QOBJECTWRAPPER_P_H - - diff --git a/src/qml/qml/v8/qv8sequencewrapper.cpp b/src/qml/qml/v8/qv8sequencewrapper.cpp deleted file mode 100644 index b1e0c41771..0000000000 --- a/src/qml/qml/v8/qv8sequencewrapper.cpp +++ /dev/null @@ -1,323 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <QtQml/qqml.h> - -#include "qv8sequencewrapper_p.h" -#include "qv8sequencewrapper_p_p.h" -#include "qv8engine_p.h" - -QT_BEGIN_NAMESPACE - -QV8SequenceWrapper::QV8SequenceWrapper() - : m_engine(0) -{ -} - -QV8SequenceWrapper::~QV8SequenceWrapper() -{ -} - -#define REGISTER_QML_SEQUENCE_METATYPE(unused, unused2, SequenceType, unused3) qRegisterMetaType<SequenceType>(); -void QV8SequenceWrapper::init(QV8Engine *engine) -{ - FOREACH_QML_SEQUENCE_TYPE(REGISTER_QML_SEQUENCE_METATYPE) - - m_engine = engine; - m_toString = qPersistentNew<v8::Function>(v8::FunctionTemplate::New(ToString)->GetFunction()); - m_valueOf = qPersistentNew<v8::Function>(v8::FunctionTemplate::New(ValueOf)->GetFunction()); - - QString defaultSortString = QLatin1String( - "(function compare(x,y) {" - " if (x === y) return 0;" - " x = x.toString();" - " y = y.toString();" - " if (x == y) return 0;" - " else return x < y ? -1 : 1;" - "})"); - - m_sort = qPersistentNew<v8::Function>(v8::FunctionTemplate::New(Sort)->GetFunction()); - m_arrayPrototype = qPersistentNew<v8::Value>(v8::Array::New(1)->GetPrototype()); - v8::Local<v8::Script> defaultSortCompareScript = v8::Script::Compile(engine->toString(defaultSortString)); - m_defaultSortComparer = qPersistentNew<v8::Function>(v8::Handle<v8::Function>(v8::Function::Cast(*defaultSortCompareScript->Run()))); - - v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New(); - ft->InstanceTemplate()->SetFallbackPropertyHandler(Getter, Setter); - ft->InstanceTemplate()->SetIndexedPropertyHandler(IndexedGetter, IndexedSetter, 0, IndexedDeleter, IndexedEnumerator); - ft->InstanceTemplate()->SetAccessor(v8::String::New("length"), LengthGetter, LengthSetter, - v8::Handle<v8::Value>(), v8::DEFAULT, - v8::PropertyAttribute(v8::DontDelete | v8::DontEnum)); - ft->InstanceTemplate()->SetAccessor(v8::String::New("toString"), ToStringGetter, 0, - m_toString, v8::DEFAULT, - v8::PropertyAttribute(v8::ReadOnly | v8::DontDelete | v8::DontEnum)); - ft->InstanceTemplate()->SetAccessor(v8::String::New("valueOf"), ValueOfGetter, 0, - m_valueOf, v8::DEFAULT, - v8::PropertyAttribute(v8::ReadOnly | v8::DontDelete | v8::DontEnum)); - ft->InstanceTemplate()->SetAccessor(v8::String::New("sort"), SortGetter, 0, - m_sort, v8::DEFAULT, - v8::PropertyAttribute(v8::ReadOnly | v8::DontDelete | v8::DontEnum)); - ft->InstanceTemplate()->SetHasExternalResource(true); - ft->InstanceTemplate()->MarkAsUseUserObjectComparison(); - m_constructor = qPersistentNew<v8::Function>(ft->GetFunction()); -} -#undef REGISTER_QML_SEQUENCE_METATYPE - -void QV8SequenceWrapper::destroy() -{ - qPersistentDispose(m_defaultSortComparer); - qPersistentDispose(m_sort); - qPersistentDispose(m_arrayPrototype); - qPersistentDispose(m_toString); - qPersistentDispose(m_valueOf); - qPersistentDispose(m_constructor); -} - -#define IS_SEQUENCE(unused1, unused2, SequenceType, unused3) \ - if (sequenceTypeId == qMetaTypeId<SequenceType>()) { \ - return true; \ - } else - -bool QV8SequenceWrapper::isSequenceType(int sequenceTypeId) const -{ - FOREACH_QML_SEQUENCE_TYPE(IS_SEQUENCE) { /* else */ return false; } -} -#undef IS_SEQUENCE - -bool QV8SequenceWrapper::isEqual(QV8ObjectResource *lhs, QV8ObjectResource *rhs) -{ - Q_ASSERT(lhs && rhs && lhs->resourceType() == QV8ObjectResource::SequenceType && rhs->resourceType() == QV8ObjectResource::SequenceType); - QV8SequenceResource *lr = static_cast<QV8SequenceResource *>(lhs); - QV8SequenceResource *rr = static_cast<QV8SequenceResource *>(rhs); - return lr->isEqual(rr); -} - -quint32 QV8SequenceWrapper::sequenceLength(QV8ObjectResource *r) -{ - Q_ASSERT(r->resourceType() == QV8ObjectResource::SequenceType); - QV8SequenceResource *sr = static_cast<QV8SequenceResource *>(r); - Q_ASSERT(sr); - return sr->lengthGetter(); -} - -#define NEW_REFERENCE_SEQUENCE(ElementType, ElementTypeName, SequenceType, unused) \ - if (sequenceType == qMetaTypeId<SequenceType>()) { \ - r = new QV8##ElementTypeName##SequenceResource(m_engine, object, propertyIndex); \ - } else - -v8::Local<v8::Object> QV8SequenceWrapper::newSequence(int sequenceType, QObject *object, int propertyIndex, bool *succeeded) -{ - // This function is called when the property is a QObject Q_PROPERTY of - // the given sequence type. Internally we store a typed-sequence - // (as well as object ptr + property index for updated-read and write-back) - // and so access/mutate avoids variant conversion. - *succeeded = true; - QV8SequenceResource *r = 0; - FOREACH_QML_SEQUENCE_TYPE(NEW_REFERENCE_SEQUENCE) { /* else */ *succeeded = false; return v8::Local<v8::Object>(); } - - v8::Local<v8::Object> rv = m_constructor->NewInstance(); - rv->SetExternalResource(r); - rv->SetPrototype(m_arrayPrototype); - return rv; -} -#undef NEW_REFERENCE_SEQUENCE - -#define NEW_COPY_SEQUENCE(ElementType, ElementTypeName, SequenceType, unused) \ - if (sequenceType == qMetaTypeId<SequenceType>()) { \ - r = new QV8##ElementTypeName##SequenceResource(m_engine, v.value<SequenceType>()); \ - } else - -v8::Local<v8::Object> QV8SequenceWrapper::fromVariant(const QVariant& v, bool *succeeded) -{ - // This function is called when assigning a sequence value to a normal JS var - // in a JS block. Internally, we store a sequence of the specified type. - // Access and mutation is extremely fast since it will not need to modify any - // QObject property. - int sequenceType = v.userType(); - *succeeded = true; - QV8SequenceResource *r = 0; - FOREACH_QML_SEQUENCE_TYPE(NEW_COPY_SEQUENCE) { /* else */ *succeeded = false; return v8::Local<v8::Object>(); } - - v8::Local<v8::Object> rv = m_constructor->NewInstance(); - rv->SetExternalResource(r); - rv->SetPrototype(m_arrayPrototype); - return rv; -} -#undef NEW_COPY_SEQUENCE - -QVariant QV8SequenceWrapper::toVariant(QV8ObjectResource *r) -{ - Q_ASSERT(r->resourceType() == QV8ObjectResource::SequenceType); - QV8SequenceResource *resource = static_cast<QV8SequenceResource *>(r); - return resource->toVariant(); -} - -#define SEQUENCE_TO_VARIANT(ElementType, ElementTypeName, SequenceType, unused) \ - if (typeHint == qMetaTypeId<SequenceType>()) { \ - return QV8##ElementTypeName##SequenceResource::toVariant(m_engine, array, length, succeeded); \ - } else - -QVariant QV8SequenceWrapper::toVariant(v8::Handle<v8::Array> array, int typeHint, bool *succeeded) -{ - *succeeded = true; - uint32_t length = array->Length(); - FOREACH_QML_SEQUENCE_TYPE(SEQUENCE_TO_VARIANT) { /* else */ *succeeded = false; return QVariant(); } -} -#undef SEQUENCE_TO_VARIANT - -v8::Handle<v8::Value> QV8SequenceWrapper::IndexedSetter(quint32 index, v8::Local<v8::Value> value, const v8::AccessorInfo &info) -{ - QV8SequenceResource *sr = v8_resource_cast<QV8SequenceResource>(info.This()); - Q_ASSERT(sr); - return sr->indexedSetter(index, value); -} - -v8::Handle<v8::Value> QV8SequenceWrapper::IndexedGetter(quint32 index, const v8::AccessorInfo &info) -{ - QV8SequenceResource *sr = v8_resource_cast<QV8SequenceResource>(info.This()); - Q_ASSERT(sr); - return sr->indexedGetter(index); -} - -v8::Handle<v8::Boolean> QV8SequenceWrapper::IndexedDeleter(quint32 index, const v8::AccessorInfo &info) -{ - QV8SequenceResource *sr = v8_resource_cast<QV8SequenceResource>(info.This()); - Q_ASSERT(sr); - return sr->indexedDeleter(index); -} - -v8::Handle<v8::Array> QV8SequenceWrapper::IndexedEnumerator(const v8::AccessorInfo &info) -{ - QV8SequenceResource *sr = v8_resource_cast<QV8SequenceResource>(info.This()); - Q_ASSERT(sr); - return sr->indexedEnumerator(); -} - -v8::Handle<v8::Value> QV8SequenceWrapper::LengthGetter(v8::Local<v8::String> property, const v8::AccessorInfo &info) -{ - Q_UNUSED(property); - QV8SequenceResource *sr = v8_resource_cast<QV8SequenceResource>(info.This()); - Q_ASSERT(sr); - return v8::Integer::NewFromUnsigned(sr->lengthGetter()); -} - -void QV8SequenceWrapper::LengthSetter(v8::Local<v8::String> property, v8::Local<v8::Value> value, const v8::AccessorInfo &info) -{ - Q_UNUSED(property); - QV8SequenceResource *sr = v8_resource_cast<QV8SequenceResource>(info.This()); - Q_ASSERT(sr); - sr->lengthSetter(value); -} - -v8::Handle<v8::Value> QV8SequenceWrapper::ToStringGetter(v8::Local<v8::String> property, const v8::AccessorInfo &info) -{ - Q_UNUSED(property); - return info.Data(); -} - -v8::Handle<v8::Value> QV8SequenceWrapper::ValueOfGetter(v8::Local<v8::String> property, - const v8::AccessorInfo &info) -{ - Q_UNUSED(property); - return info.Data(); -} - -v8::Handle<v8::Value> QV8SequenceWrapper::SortGetter(v8::Local<v8::String> property, const v8::AccessorInfo &info) -{ - Q_UNUSED(property); - return info.Data(); -} - -v8::Handle<v8::Value> QV8SequenceWrapper::Sort(const v8::Arguments &args) -{ - int argCount = args.Length(); - - if (argCount < 2) { - QV8SequenceResource *sr = v8_resource_cast<QV8SequenceResource>(args.This()); - Q_ASSERT(sr); - - qint32 length = sr->lengthGetter(); - if (length > 1) { - v8::Handle<v8::Function> jsCompareFn = sr->engine->sequenceWrapper()->m_defaultSortComparer; - if (argCount == 1 && args[0]->IsFunction()) - jsCompareFn = v8::Handle<v8::Function>(v8::Function::Cast(*args[0])); - - sr->sort(jsCompareFn); - } - } - - return args.This(); -} - -v8::Handle<v8::Value> QV8SequenceWrapper::ToString(const v8::Arguments &args) -{ - QV8SequenceResource *sr = v8_resource_cast<QV8SequenceResource>(args.This()); - Q_ASSERT(sr); - return sr->toString(); -} - -v8::Handle<v8::Value> QV8SequenceWrapper::ValueOf(const v8::Arguments &args) -{ - QV8SequenceResource *sr = v8_resource_cast<QV8SequenceResource>(args.This()); - Q_ASSERT(sr); - v8::Handle<v8::Value> tostringValue = sr->toString(); - if (!tostringValue.IsEmpty()) - return tostringValue; - return v8::Integer::NewFromUnsigned(sr->lengthGetter()); -} - -v8::Handle<v8::Value> QV8SequenceWrapper::Getter(v8::Local<v8::String> property, - const v8::AccessorInfo &info) -{ - Q_UNUSED(property); - Q_UNUSED(info); - return v8::Handle<v8::Value>(); -} - -v8::Handle<v8::Value> QV8SequenceWrapper::Setter(v8::Local<v8::String> property, - v8::Local<v8::Value> value, - const v8::AccessorInfo &info) -{ - Q_UNUSED(property); - Q_UNUSED(info); - return value; -} - -QT_END_NAMESPACE diff --git a/src/qml/qml/v8/qv8sequencewrapper_p.h b/src/qml/qml/v8/qv8sequencewrapper_p.h deleted file mode 100644 index c403abc6b6..0000000000 --- a/src/qml/qml/v8/qv8sequencewrapper_p.h +++ /dev/null @@ -1,114 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QV8SEQUENCEWRAPPER_P_H -#define QV8SEQUENCEWRAPPER_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <QtCore/qglobal.h> -#include <QtCore/qvariant.h> -#include <private/qv8_p.h> - -QT_BEGIN_NAMESPACE - -class QV8Engine; -class QV8ObjectResource; - -class QV8SequenceWrapper -{ -public: - QV8SequenceWrapper(); - ~QV8SequenceWrapper(); - - void init(QV8Engine *); - void destroy(); - - bool isSequenceType(int sequenceTypeId) const; - - bool isEqual(QV8ObjectResource *lhs, const QVariant &rhs); - bool isEqual(QV8ObjectResource *lhs, QV8ObjectResource *rhs); - quint32 sequenceLength(QV8ObjectResource *); - - v8::Local<v8::Object> newSequence(int sequenceTypeId, QObject *object, int propertyIndex, bool *succeeded); - v8::Local<v8::Object> fromVariant(const QVariant& v, bool *succeeded); - QVariant toVariant(QV8ObjectResource *); - QVariant toVariant(v8::Handle<v8::Array> array, int typeHint, bool *succeeded); - -private: - QV8Engine *m_engine; - - v8::Persistent<v8::Function> m_constructor; - v8::Persistent<v8::Function> m_toString; - v8::Persistent<v8::Function> m_valueOf; - v8::Persistent<v8::Function> m_sort; - v8::Persistent<v8::Value> m_arrayPrototype; - v8::Persistent<v8::Function> m_defaultSortComparer; - - static v8::Handle<v8::Value> IndexedGetter(quint32 index, const v8::AccessorInfo &info); - static v8::Handle<v8::Value> IndexedSetter(quint32 index, v8::Local<v8::Value> value, const v8::AccessorInfo &info); - static v8::Handle<v8::Boolean> IndexedDeleter(quint32 index, const v8::AccessorInfo &info); - static v8::Handle<v8::Array> IndexedEnumerator(const v8::AccessorInfo &info); - static v8::Handle<v8::Value> LengthGetter(v8::Local<v8::String> property, const v8::AccessorInfo &info); - static void LengthSetter(v8::Local<v8::String> property, v8::Local<v8::Value> value, const v8::AccessorInfo &info); - static v8::Handle<v8::Value> ToStringGetter(v8::Local<v8::String> property, const v8::AccessorInfo &info); - static v8::Handle<v8::Value> ToString(const v8::Arguments &args); - static v8::Handle<v8::Value> ValueOfGetter(v8::Local<v8::String> property, const v8::AccessorInfo &info); - static v8::Handle<v8::Value> SortGetter(v8::Local<v8::String> property, const v8::AccessorInfo &info); - static v8::Handle<v8::Value> ValueOf(const v8::Arguments &args); - static v8::Handle<v8::Value> Getter(v8::Local<v8::String> property, const v8::AccessorInfo &info); - static v8::Handle<v8::Value> Setter(v8::Local<v8::String> property, v8::Local<v8::Value> value, const v8::AccessorInfo &info); - static v8::Handle<v8::Value> Sort(const v8::Arguments &args); -}; - - -QT_END_NAMESPACE - -#endif // QV8SEQUENCEWRAPPER_P_H diff --git a/src/qml/qml/v8/qv8sequencewrapper_p_p.h b/src/qml/qml/v8/qv8sequencewrapper_p_p.h deleted file mode 100644 index ff9df7d4a0..0000000000 --- a/src/qml/qml/v8/qv8sequencewrapper_p_p.h +++ /dev/null @@ -1,512 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QV8SEQUENCEWRAPPER_P_P_H -#define QV8SEQUENCEWRAPPER_P_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <private/qqmlengine_p.h> -#include <private/qqmlmetatype_p.h> - -QT_BEGIN_NAMESPACE - -/*! - \internal - \class QV8SequenceResource - \brief The abstract base class of the external resource used in sequence type objects - - Every sequence type object returned by QV8SequenceWrapper::fromVariant() or - QV8SequenceWrapper::newSequence() has a type-specific QV8SequenceResource which - contains the type name, the meta type ids of the sequence and sequence element - types, as well as either the sequence data (copy) or object pointer and property - index (reference) data associated with the sequence. - */ -class QV8SequenceResource : public QV8ObjectResource -{ - V8_RESOURCE_TYPE(SequenceType) - -public: - virtual ~QV8SequenceResource() {} - - enum ObjectType { Reference, Copy }; - - virtual QVariant toVariant() = 0; - virtual bool isEqual(const QV8SequenceResource *v) = 0; - - virtual quint32 lengthGetter() = 0; - virtual void lengthSetter(v8::Handle<v8::Value> value) = 0; - virtual v8::Handle<v8::Value> indexedSetter(quint32 index, v8::Handle<v8::Value> value) = 0; - virtual v8::Handle<v8::Value> indexedGetter(quint32 index) = 0; - virtual v8::Handle<v8::Boolean> indexedDeleter(quint32 index) = 0; - virtual v8::Handle<v8::Array> indexedEnumerator() = 0; - virtual v8::Handle<v8::Value> toString() = 0; - virtual void sort(v8::Handle<v8::Function> comparer) = 0; - - ObjectType objectType; - QByteArray typeName; - int sequenceMetaTypeId; - int elementMetaTypeId; - -protected: - QV8SequenceResource(QV8Engine *engine, ObjectType type, const QByteArray &name, int sequenceId, int elementId) - : QV8ObjectResource(engine), objectType(type), typeName(name), sequenceMetaTypeId(sequenceId), elementMetaTypeId(elementId) - { - } -}; - -// helper function to generate valid warnings if errors occur during sequence operations. -static void generateWarning(QV8Engine *engine, const QString& description) -{ - if (!engine) - return; - v8::Local<v8::StackTrace> currStack = v8::StackTrace::CurrentStackTrace(1); - if (currStack.IsEmpty()) - return; - v8::Local<v8::StackFrame> currFrame = currStack->GetFrame(0); - if (currFrame.IsEmpty()) - return; - - QQmlError retn; - retn.setDescription(description); - retn.setLine(currFrame->GetLineNumber()); - retn.setUrl(QUrl(engine->toString(currFrame->GetScriptName()))); - QQmlEnginePrivate::warning(engine->engine(), retn); -} - - -static int convertV8ValueToInt(QV8Engine *, v8::Handle<v8::Value> v) -{ - return v->Int32Value(); -} - -static v8::Handle<v8::Value> convertIntToV8Value(QV8Engine *, int v) -{ - return v8::Integer::New(v); -} - -static QString convertIntToString(QV8Engine *, int v) -{ - return QString::number(v); -} - -static qreal convertV8ValueToReal(QV8Engine *, v8::Handle<v8::Value> v) -{ - return v->NumberValue(); -} - -static v8::Handle<v8::Value> convertRealToV8Value(QV8Engine *, qreal v) -{ - return v8::Number::New(v); -} - -static QString convertRealToString(QV8Engine *, qreal v) -{ - return QString::number(v); -} - -static bool convertV8ValueToBool(QV8Engine *, v8::Handle<v8::Value> v) -{ - return v->BooleanValue(); -} - -static v8::Handle<v8::Value> convertBoolToV8Value(QV8Engine *, bool v) -{ - return v8::Boolean::New(v); -} - -static QString convertBoolToString(QV8Engine *, bool v) -{ - if (v) - return QLatin1String("true"); - return QLatin1String("false"); -} - -static QString convertV8ValueToString(QV8Engine *e, v8::Handle<v8::Value> v) -{ - return e->toString(v->ToString()); -} - -static v8::Handle<v8::Value> convertStringToV8Value(QV8Engine *e, const QString &v) -{ - return e->toString(v); -} - -static QString convertStringToString(QV8Engine *, const QString &v) -{ - return v; -} - -static QString convertV8ValueToQString(QV8Engine *e, v8::Handle<v8::Value> v) -{ - return e->toString(v->ToString()); -} - -static v8::Handle<v8::Value> convertQStringToV8Value(QV8Engine *e, const QString &v) -{ - return e->toString(v); -} - -static QString convertQStringToString(QV8Engine *, const QString &v) -{ - return v; -} - -static QUrl convertV8ValueToUrl(QV8Engine *e, v8::Handle<v8::Value> v) -{ - return QUrl(e->toString(v->ToString())); -} - -static v8::Handle<v8::Value> convertUrlToV8Value(QV8Engine *e, const QUrl &v) -{ - return e->toString(QLatin1String(v.toEncoded().data())); -} - -static QString convertUrlToString(QV8Engine *, const QUrl &v) -{ - return v.toString(); -} - - -/* - \internal - \class QV8<Type>SequenceResource - \brief The external resource used in sequence type objects - - Every sequence type object returned by QV8SequenceWrapper::newSequence() has - a QV8<Type>SequenceResource which contains a property index and a pointer - to the object which contains the property. - - Every sequence type object returned by QV8SequenceWrapper::fromVariant() has - a QV8<Type>SequenceResource which contains a copy of the sequence value. - Operations on the sequence are implemented directly in terms of that sequence data. - - There exists one QV8<Type>SequenceResource instance for every JavaScript Object - (sequence) instance returned from QV8SequenceWrapper::newSequence() or - QV8SequenceWrapper::fromVariant(). - */ - -// F(elementType, elementTypeName, sequenceType, defaultValue) -#define FOREACH_QML_SEQUENCE_TYPE(F) \ - F(int, Int, QList<int>, 0) \ - F(qreal, Real, QList<qreal>, 0.0) \ - F(bool, Bool, QList<bool>, false) \ - F(QString, String, QList<QString>, QString()) \ - F(QString, QString, QStringList, QString()) \ - F(QUrl, Url, QList<QUrl>, QUrl()) - -#define QML_SEQUENCE_TYPE_RESOURCE(SequenceElementType, SequenceElementTypeName, SequenceType, DefaultValue, ConversionToV8fn, ConversionFromV8fn, ToStringfn) \ - QT_END_NAMESPACE \ - Q_DECLARE_METATYPE(SequenceType) \ - QT_BEGIN_NAMESPACE \ - class QV8##SequenceElementTypeName##SequenceResource : public QV8SequenceResource { \ - public:\ - QV8##SequenceElementTypeName##SequenceResource(QV8Engine *engine, QObject *obj, int propIdx) \ - : QV8SequenceResource(engine, QV8SequenceResource::Reference, #SequenceType, qMetaTypeId<SequenceType>(), qMetaTypeId<SequenceElementType>()) \ - , object(obj), propertyIndex(propIdx) \ - { \ - } \ - QV8##SequenceElementTypeName##SequenceResource(QV8Engine *engine, const SequenceType &value) \ - : QV8SequenceResource(engine, QV8SequenceResource::Copy, #SequenceType, qMetaTypeId<SequenceType>(), qMetaTypeId<SequenceElementType>()) \ - , object(0), propertyIndex(-1), c(value) \ - { \ - } \ - ~QV8##SequenceElementTypeName##SequenceResource() \ - { \ - } \ - static QVariant toVariant(QV8Engine *e, v8::Handle<v8::Array> array, uint32_t length, bool *succeeded) \ - { \ - SequenceType list; \ - list.reserve(length); \ - for (uint32_t ii = 0; ii < length; ++ii) { \ - list.append(ConversionFromV8fn(e, array->Get(ii))); \ - } \ - *succeeded = true; \ - return QVariant::fromValue<SequenceType>(list); \ - } \ - QVariant toVariant() \ - { \ - if (objectType == QV8SequenceResource::Reference) { \ - if (!object) \ - return QVariant(); \ - loadReference(); \ - } \ - return QVariant::fromValue<SequenceType>(c); \ - } \ - bool isEqual(const QV8SequenceResource *v) \ - { \ - /* Note: two different sequences can never be equal (even if they */ \ - /* contain the same elements in the same order) in order to */ \ - /* maintain JavaScript semantics. However, if they both reference */ \ - /* the same QObject+propertyIndex, they are equal. */ \ - if (objectType == QV8SequenceResource::Reference && v->objectType == QV8SequenceResource::Reference) { \ - if (sequenceMetaTypeId == v->sequenceMetaTypeId) { \ - const QV8##SequenceElementTypeName##SequenceResource *rhs = static_cast<const QV8##SequenceElementTypeName##SequenceResource *>(v); \ - return (object != 0 && object == rhs->object && propertyIndex == rhs->propertyIndex); \ - } \ - } else if (objectType == QV8SequenceResource::Copy && v->objectType == QV8SequenceResource::Copy) { \ - if (sequenceMetaTypeId == v->sequenceMetaTypeId) { \ - const QV8##SequenceElementTypeName##SequenceResource *rhs = static_cast<const QV8##SequenceElementTypeName##SequenceResource *>(v); \ - return (this == rhs); \ - } \ - } \ - return false; \ - } \ - quint32 lengthGetter() \ - { \ - if (objectType == QV8SequenceResource::Reference) { \ - if (!object) \ - return 0; \ - loadReference(); \ - } \ - return static_cast<quint32>(c.count()); \ - } \ - void lengthSetter(v8::Handle<v8::Value> value) \ - { \ - /* Get the new required length */ \ - if (value.IsEmpty() || !value->IsUint32()) \ - return; \ - quint32 newLength = value->Uint32Value(); \ - /* Qt containers have int (rather than uint) allowable indexes. */ \ - if (newLength > INT_MAX) { \ - generateWarning(engine, QLatin1String("Index out of range during length set")); \ - return; \ - } \ - /* Read the sequence from the QObject property if we're a reference */ \ - if (objectType == QV8SequenceResource::Reference) { \ - if (!object) \ - return; \ - loadReference(); \ - } \ - /* Determine whether we need to modify the sequence */ \ - qint32 newCount = static_cast<qint32>(newLength); \ - qint32 count = c.count(); \ - if (newCount == count) { \ - return; \ - } else if (newCount > count) { \ - /* according to ECMA262r3 we need to insert */ \ - /* undefined values increasing length to newLength. */ \ - /* We cannot, so we insert default-values instead. */ \ - c.reserve(newCount); \ - while (newCount > count++) { \ - c.append(DefaultValue); \ - } \ - } else { \ - /* according to ECMA262r3 we need to remove */ \ - /* elements until the sequence is the required length. */ \ - while (newCount < count) { \ - count--; \ - c.removeAt(count); \ - } \ - } \ - /* write back if required. */ \ - if (objectType == QV8SequenceResource::Reference) { \ - /* write back. already checked that object is non-null, so skip that check here. */ \ - storeReference(); \ - } \ - return; \ - } \ - v8::Handle<v8::Value> indexedSetter(quint32 index, v8::Handle<v8::Value> value) \ - { \ - /* Qt containers have int (rather than uint) allowable indexes. */ \ - if (index > INT_MAX) { \ - generateWarning(engine, QLatin1String("Index out of range during indexed set")); \ - return v8::Undefined(); \ - } \ - if (objectType == QV8SequenceResource::Reference) { \ - if (!object) \ - return v8::Undefined(); \ - loadReference(); \ - } \ - /* modify the sequence */ \ - SequenceElementType elementValue = ConversionFromV8fn(engine, value); \ - qint32 count = c.count(); \ - qint32 signedIdx = static_cast<qint32>(index); \ - if (signedIdx == count) { \ - c.append(elementValue); \ - } else if (signedIdx < count) { \ - c[index] = elementValue; \ - } else { \ - /* according to ECMA262r3 we need to insert */ \ - /* the value at the given index, increasing length to index+1. */ \ - c.reserve(signedIdx + 1); \ - while (signedIdx > count++) { \ - c.append(DefaultValue); \ - } \ - c.append(elementValue); \ - } \ - /* write back. already checked that object is non-null, so skip that check here. */ \ - if (objectType == QV8SequenceResource::Reference) \ - storeReference(); \ - return value; \ - } \ - v8::Handle<v8::Value> indexedGetter(quint32 index) \ - { \ - /* Qt containers have int (rather than uint) allowable indexes. */ \ - if (index > INT_MAX) { \ - generateWarning(engine, QLatin1String("Index out of range during indexed get")); \ - return v8::Undefined(); \ - } \ - if (objectType == QV8SequenceResource::Reference) { \ - if (!object) \ - return v8::Undefined(); \ - loadReference(); \ - } \ - qint32 count = c.count(); \ - qint32 signedIdx = static_cast<qint32>(index); \ - if (signedIdx < count) \ - return ConversionToV8fn(engine, c.at(signedIdx)); \ - return v8::Undefined(); \ - } \ - v8::Handle<v8::Boolean> indexedDeleter(quint32 index) \ - { \ - /* Qt containers have int (rather than uint) allowable indexes. */ \ - if (index > INT_MAX) \ - return v8::Boolean::New(false); \ - /* Read in the sequence from the QObject */ \ - if (objectType == QV8SequenceResource::Reference) { \ - if (!object) \ - return v8::Boolean::New(false); \ - loadReference(); \ - } \ - qint32 signedIdx = static_cast<qint32>(index); \ - if (signedIdx < c.count()) { \ - /* according to ECMA262r3 it should be Undefined, */ \ - /* but we cannot, so we insert a default-value instead. */ \ - c.replace(signedIdx, DefaultValue); \ - if (objectType == QV8SequenceResource::Reference) { \ - /* write back. already checked that object is non-null, so skip that check here. */ \ - storeReference(); \ - } \ - return v8::Boolean::New(true); \ - } \ - return v8::Boolean::New(false); \ - } \ - v8::Handle<v8::Array> indexedEnumerator() \ - { \ - if (objectType == QV8SequenceResource::Reference) { \ - if (!object) \ - return v8::Handle<v8::Array>(); \ - loadReference(); \ - } \ - qint32 count = c.count(); \ - v8::Local<v8::Array> retn = v8::Array::New(count); \ - for (qint32 i = 0; i < count; ++i) { \ - retn->Set(static_cast<quint32>(i), v8::Integer::NewFromUnsigned(static_cast<quint32>(i))); \ - } \ - return retn; \ - } \ - v8::Handle<v8::Value> toString() \ - { \ - if (objectType == QV8SequenceResource::Reference) { \ - if (!object) \ - return v8::Undefined(); \ - loadReference(); \ - } \ - QString str; \ - qint32 count = c.count(); \ - for (qint32 i = 0; i < count; ++i) { \ - str += QString(QLatin1String("%1,")).arg(ToStringfn(engine, c[i])); \ - } \ - str.chop(1); \ - return engine->toString(str); \ - } \ - void loadReference() \ - { \ - Q_ASSERT(object); \ - Q_ASSERT(objectType == QV8SequenceResource::Reference); \ - void *a[] = { &c, 0 }; \ - QMetaObject::metacall(object, QMetaObject::ReadProperty, propertyIndex, a); \ - } \ - void storeReference() \ - { \ - Q_ASSERT(object); \ - Q_ASSERT(objectType == QV8SequenceResource::Reference); \ - int status = -1; \ - QQmlPropertyPrivate::WriteFlags flags = \ - QQmlPropertyPrivate::DontRemoveBinding; \ - void *a[] = { &c, 0, &status, &flags }; \ - QMetaObject::metacall(object, QMetaObject::WriteProperty, propertyIndex, a); \ - } \ - class CompareFunctor \ - { \ - public: \ - CompareFunctor(QV8Engine *engine, v8::Handle<v8::Function> f) : jsFn(f), eng(engine) {} \ - bool operator()(SequenceElementType e0, SequenceElementType e1) \ - { \ - v8::Handle<v8::Value> argv[2] = { eng->fromVariant(e0), eng->fromVariant(e1) }; \ - v8::Handle<v8::Value> compareValue = jsFn->Call(eng->global(), 2, argv); \ - return compareValue->NumberValue() < 0; \ - } \ - private: \ - v8::Handle<v8::Function> jsFn; \ - QV8Engine *eng; \ - }; \ - void sort(v8::Handle<v8::Function> jsCompareFunction) \ - { \ - CompareFunctor cf(engine, jsCompareFunction); \ - qSort(c.begin(), c.end(), cf); \ - } \ - private: \ - QQmlGuard<QObject> object; \ - int propertyIndex; \ - SequenceType c; \ - }; - -#define GENERATE_QML_SEQUENCE_TYPE_RESOURCE(ElementType, ElementTypeName, SequenceType, DefaultValue) \ - QML_SEQUENCE_TYPE_RESOURCE(ElementType, ElementTypeName, SequenceType, DefaultValue, convert##ElementTypeName##ToV8Value, convertV8ValueTo##ElementTypeName, convert##ElementTypeName##ToString) - -FOREACH_QML_SEQUENCE_TYPE(GENERATE_QML_SEQUENCE_TYPE_RESOURCE) -#undef GENERATE_QML_SEQUENCE_TYPE_RESOURCE -#undef QML_SEQUENCE_TYPE_RESOURCE - -QT_END_NAMESPACE - -#endif // QV8SEQUENCEWRAPPER_P_P_H diff --git a/src/qml/qml/v8/qv8sqlerrors.cpp b/src/qml/qml/v8/qv8sqlerrors.cpp deleted file mode 100644 index e06069cddd..0000000000 --- a/src/qml/qml/v8/qv8sqlerrors.cpp +++ /dev/null @@ -1,64 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qv8sqlerrors_p.h" -#include "qv8engine_p.h" - -QT_BEGIN_NAMESPACE - -void qt_add_sqlexceptions(QV8Engine *engine) -{ - // SQL Exception - v8::PropertyAttribute attributes = (v8::PropertyAttribute)(v8::ReadOnly | v8::DontEnum | v8::DontDelete); - - v8::Local<v8::Object> sqlexception = v8::Object::New(); - sqlexception->Set(v8::String::New("UNKNOWN_ERR"), v8::Integer::New(SQLEXCEPTION_UNKNOWN_ERR), attributes); - sqlexception->Set(v8::String::New("DATABASE_ERR"), v8::Integer::New(SQLEXCEPTION_DATABASE_ERR), attributes); - sqlexception->Set(v8::String::New("VERSION_ERR"), v8::Integer::New(SQLEXCEPTION_VERSION_ERR), attributes); - sqlexception->Set(v8::String::New("TOO_LARGE_ERR"), v8::Integer::New(SQLEXCEPTION_TOO_LARGE_ERR), attributes); - sqlexception->Set(v8::String::New("QUOTA_ERR"), v8::Integer::New(SQLEXCEPTION_QUOTA_ERR), attributes); - sqlexception->Set(v8::String::New("SYNTAX_ERR"), v8::Integer::New(SQLEXCEPTION_SYNTAX_ERR), attributes); - sqlexception->Set(v8::String::New("CONSTRAINT_ERR"), v8::Integer::New(SQLEXCEPTION_CONSTRAINT_ERR), attributes); - sqlexception->Set(v8::String::New("TIMEOUT_ERR"), v8::Integer::New(SQLEXCEPTION_TIMEOUT_ERR), attributes); - engine->global()->Set(v8::String::New("SQLException"), sqlexception); -} - -QT_END_NAMESPACE diff --git a/src/qml/qml/v8/qv8stringwrapper_p.h b/src/qml/qml/v8/qv8stringwrapper_p.h deleted file mode 100644 index 6720e06199..0000000000 --- a/src/qml/qml/v8/qv8stringwrapper_p.h +++ /dev/null @@ -1,78 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QQMLV8STRINGWRAPPER_P_H -#define QQMLV8STRINGWRAPPER_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <private/qtqmlglobal_p.h> - -#include <QtCore/qstring.h> -#include <private/qv8_p.h> - -QT_BEGIN_NAMESPACE - -class Q_QML_PRIVATE_EXPORT QV8StringWrapper -{ -public: - QV8StringWrapper(); - ~QV8StringWrapper(); - - void init(); - void destroy(); - - v8::Local<v8::String> toString(const QString &); - QString toString(v8::Handle<v8::String>); -}; - -QT_END_NAMESPACE - -#endif // QQMLV8STRINGWRAPPER_P_H diff --git a/src/qml/qml/v8/qv8typewrapper.cpp b/src/qml/qml/v8/qv8typewrapper.cpp deleted file mode 100644 index 820f0b3ee6..0000000000 --- a/src/qml/qml/v8/qv8typewrapper.cpp +++ /dev/null @@ -1,307 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qv8contextwrapper_p.h" -#include "qv8engine_p.h" - -#include <private/qqmlengine_p.h> -#include <private/qqmlcontext_p.h> - -#include <private/qjsvalue_p.h> -#include <private/qscript_impl_p.h> - -QT_BEGIN_NAMESPACE - -class QV8TypeResource : public QV8ObjectResource -{ - V8_RESOURCE_TYPE(TypeType) - -public: - QV8TypeResource(QV8Engine *engine); - virtual ~QV8TypeResource(); - - QV8TypeWrapper::TypeNameMode mode; - - QQmlGuard<QObject> object; - - QQmlType *type; - QQmlTypeNameCache *typeNamespace; - const void *importNamespace; -}; - -QV8TypeResource::QV8TypeResource(QV8Engine *engine) -: QV8ObjectResource(engine), mode(QV8TypeWrapper::IncludeEnums), type(0), typeNamespace(0), importNamespace(0) -{ -} - -QV8TypeResource::~QV8TypeResource() -{ - if (typeNamespace) typeNamespace->release(); -} - -QV8TypeWrapper::QV8TypeWrapper() -: m_engine(0) -{ -} - -QV8TypeWrapper::~QV8TypeWrapper() -{ -} - -void QV8TypeWrapper::destroy() -{ - qPersistentDispose(m_constructor); -} - -void QV8TypeWrapper::init(QV8Engine *engine) -{ - m_engine = engine; - v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New(); - ft->InstanceTemplate()->SetNamedPropertyHandler(Getter, Setter); - ft->InstanceTemplate()->SetHasExternalResource(true); - m_constructor = qPersistentNew<v8::Function>(ft->GetFunction()); -} - -// Returns a type wrapper for type t on o. This allows access of enums, and attached properties. -v8::Local<v8::Object> QV8TypeWrapper::newObject(QObject *o, QQmlType *t, TypeNameMode mode) -{ - Q_ASSERT(t); - // XXX NewInstance() should be optimized - v8::Local<v8::Object> rv = m_constructor->NewInstance(); - QV8TypeResource *r = new QV8TypeResource(m_engine); - r->mode = mode; r->object = o; r->type = t; - rv->SetExternalResource(r); - return rv; -} - -// Returns a type wrapper for importNamespace (of t) on o. This allows nested resolution of a type in a -// namespace. -v8::Local<v8::Object> QV8TypeWrapper::newObject(QObject *o, QQmlTypeNameCache *t, - const void *importNamespace, TypeNameMode mode) -{ - Q_ASSERT(t); - Q_ASSERT(importNamespace); - // XXX NewInstance() should be optimized - v8::Local<v8::Object> rv = m_constructor->NewInstance(); - QV8TypeResource *r = new QV8TypeResource(m_engine); - t->addref(); - r->mode = mode; r->object = o; r->typeNamespace = t; r->importNamespace = importNamespace; - rv->SetExternalResource(r); - return rv; -} - -QVariant QV8TypeWrapper::toVariant(QV8ObjectResource *r) -{ - Q_ASSERT(r->resourceType() == QV8ObjectResource::TypeType); - QV8TypeResource *resource = static_cast<QV8TypeResource *>(r); - QV8Engine *v8engine = resource->engine; - - if (resource->type && resource->type->isSingleton()) { - QQmlEngine *e = v8engine->engine(); - QQmlType::SingletonInstanceInfo *siinfo = resource->type->singletonInstanceInfo(); - siinfo->init(e); // note: this will also create QJSValue singleton which isn't strictly required. - QObject *qobjectSingleton = siinfo->qobjectApi(e); - if (qobjectSingleton) { - return QVariant::fromValue<QObject*>(qobjectSingleton); - } - } - - // only QObject Singleton Type can be converted to a variant. - return QVariant(); -} - -v8::Handle<v8::Value> QV8TypeWrapper::Getter(v8::Local<v8::String> property, - const v8::AccessorInfo &info) -{ - QV8TypeResource *resource = v8_resource_cast<QV8TypeResource>(info.This()); - - if (!resource) - return v8::Undefined(); - - QV8Engine *v8engine = resource->engine; - QQmlContextData *context = v8engine->callingContext(); - - QObject *object = resource->object; - - QHashedV8String propertystring(property); - - if (resource->type) { - QQmlType *type = resource->type; - - // singleton types are handled differently to other types. - if (type->isSingleton()) { - QQmlEngine *e = v8engine->engine(); - QQmlType::SingletonInstanceInfo *siinfo = type->singletonInstanceInfo(); - siinfo->init(e); - - QObject *qobjectSingleton = siinfo->qobjectApi(e); - if (qobjectSingleton) { - // check for enum value - if (QV8Engine::startsWithUpper(property)) { - if (resource->mode == IncludeEnums) { - QString name = v8engine->toString(property); - - // ### Optimize - QByteArray enumName = name.toUtf8(); - const QMetaObject *metaObject = qobjectSingleton->metaObject(); - for (int ii = metaObject->enumeratorCount() - 1; ii >= 0; --ii) { - QMetaEnum e = metaObject->enumerator(ii); - bool ok; - int value = e.keyToValue(enumName.constData(), &ok); - if (ok) - return v8::Integer::New(value); - } - } - } - - // check for property. - v8::Handle<v8::Value> rv = v8engine->qobjectWrapper()->getProperty(qobjectSingleton, propertystring, context, QV8QObjectWrapper::IgnoreRevision); - return rv; - } else if (!siinfo->scriptApi(e).isUndefined()) { - // NOTE: if used in a binding, changes will not trigger re-evaluation since non-NOTIFYable. - QJSValuePrivate *apiprivate = QJSValuePrivate::get(siinfo->scriptApi(e)); - QScopedPointer<QJSValuePrivate> propertyValue(apiprivate->property(property).give()); - return propertyValue->asV8Value(v8engine); - } - - // Fall through to return empty handle - - } else { - - if (QV8Engine::startsWithUpper(property)) { - bool ok = false; - int value = type->enumValue(propertystring, &ok); - if (ok) - return v8::Integer::New(value); - - // Fall through to return empty handle - - } else if (resource->object) { - QObject *ao = qmlAttachedPropertiesObjectById(type->attachedPropertiesId(), object); - if (ao) - return v8engine->qobjectWrapper()->getProperty(ao, propertystring, context, - QV8QObjectWrapper::IgnoreRevision); - - // Fall through to return empty handle - } - - // Fall through to return empty handle - } - - // Fall through to return empty handle - - } else if (resource->typeNamespace) { - Q_ASSERT(resource->importNamespace); - QQmlTypeNameCache::Result r = resource->typeNamespace->query(propertystring, - resource->importNamespace); - - if (r.isValid()) { - QQmlContextData *context = v8engine->callingContext(); - if (r.type) { - return v8engine->typeWrapper()->newObject(object, r.type, resource->mode); - } else if (r.scriptIndex != -1) { - int index = r.scriptIndex; - if (index < context->importedScripts.count()) - return context->importedScripts.at(index); - } else if (r.importNamespace) { - return v8engine->typeWrapper()->newObject(object, context->imports, r.importNamespace); - } - - return v8::Undefined(); - - } - - // Fall through to return empty handle - - } else { - Q_ASSERT(!"Unreachable"); - } - - return v8::Handle<v8::Value>(); -} - -v8::Handle<v8::Value> QV8TypeWrapper::Setter(v8::Local<v8::String> property, - v8::Local<v8::Value> value, - const v8::AccessorInfo &info) -{ - QV8TypeResource *resource = v8_resource_cast<QV8TypeResource>(info.This()); - - if (!resource) - return value; - - QV8Engine *v8engine = resource->engine; - QQmlContextData *context = v8engine->callingContext(); - - QHashedV8String propertystring(property); - - QQmlType *type = resource->type; - if (type && !type->isSingleton() && resource->object) { - QObject *object = resource->object; - QObject *ao = qmlAttachedPropertiesObjectById(type->attachedPropertiesId(), object); - if (ao) - v8engine->qobjectWrapper()->setProperty(ao, propertystring, context, value, - QV8QObjectWrapper::IgnoreRevision); - } else if (type && type->isSingleton()) { - QQmlEngine *e = v8engine->engine(); - QQmlType::SingletonInstanceInfo *siinfo = type->singletonInstanceInfo(); - siinfo->init(e); - - QObject *qobjectSingleton = siinfo->qobjectApi(e); - if (qobjectSingleton) { - v8engine->qobjectWrapper()->setProperty(qobjectSingleton, propertystring, context, value, - QV8QObjectWrapper::IgnoreRevision); - } else if (!siinfo->scriptApi(e).isUndefined()) { - QScopedPointer<QJSValuePrivate> setvalp(new QJSValuePrivate(v8engine, value)); - QJSValuePrivate *apiprivate = QJSValuePrivate::get(siinfo->scriptApi(e)); - if (apiprivate->propertyFlags(property) & QJSValuePrivate::ReadOnly) { - QString error = QLatin1String("Cannot assign to read-only property \"") + - v8engine->toString(property) + QLatin1Char('\"'); - v8::ThrowException(v8::Exception::Error(v8engine->toString(error))); - } else { - apiprivate->setProperty(property, setvalp.data()); - } - } - } - - return value; -} - -QT_END_NAMESPACE diff --git a/src/qml/qml/v8/qv8typewrapper_p.h b/src/qml/qml/v8/qv8typewrapper_p.h deleted file mode 100644 index 852f49770b..0000000000 --- a/src/qml/qml/v8/qv8typewrapper_p.h +++ /dev/null @@ -1,94 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QV8TYPEWRAPPER_P_H -#define QV8TYPEWRAPPER_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <QtCore/qglobal.h> -#include <private/qv8_p.h> - -QT_BEGIN_NAMESPACE - -class QObject; -class QV8Engine; -class QQmlType; -class QQmlTypeNameCache; -class QV8TypeWrapper -{ -public: - QV8TypeWrapper(); - ~QV8TypeWrapper(); - - void init(QV8Engine *); - void destroy(); - - enum TypeNameMode { IncludeEnums, ExcludeEnums }; - v8::Local<v8::Object> newObject(QObject *, QQmlType *, TypeNameMode = IncludeEnums); - v8::Local<v8::Object> newObject(QObject *, QQmlTypeNameCache *, const void *, - TypeNameMode = IncludeEnums); - QVariant toVariant(QV8ObjectResource *); - -private: - static v8::Handle<v8::Value> Getter(v8::Local<v8::String> property, - const v8::AccessorInfo &info); - static v8::Handle<v8::Value> Setter(v8::Local<v8::String> property, - v8::Local<v8::Value> value, - const v8::AccessorInfo &info); - - QV8Engine *m_engine; - v8::Persistent<v8::Function> m_constructor; -}; - -QT_END_NAMESPACE - -#endif // QV8TYPEWRAPPER_P_H - diff --git a/src/qml/qml/v8/qv8valuetypewrapper.cpp b/src/qml/qml/v8/qv8valuetypewrapper.cpp deleted file mode 100644 index d5d977d9c4..0000000000 --- a/src/qml/qml/v8/qv8valuetypewrapper.cpp +++ /dev/null @@ -1,452 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qv8valuetypewrapper_p.h" -#include "qv8engine_p.h" - -#include <private/qqmlvaluetype_p.h> -#include <private/qqmlbinding_p.h> -#include <private/qqmlglobal_p.h> - -QT_BEGIN_NAMESPACE - -class QV8ValueTypeResource : public QV8ObjectResource -{ - V8_RESOURCE_TYPE(ValueTypeType) - -public: - enum ObjectType { Reference, Copy }; - - QV8ValueTypeResource(QV8Engine *engine, ObjectType objectType); - - ObjectType objectType; - QQmlValueType *type; -}; - -class QV8ValueTypeReferenceResource : public QV8ValueTypeResource -{ -public: - QV8ValueTypeReferenceResource(QV8Engine *engine); - - QQmlGuard<QObject> object; - int property; -}; - -class QV8ValueTypeCopyResource : public QV8ValueTypeResource -{ -public: - QV8ValueTypeCopyResource(QV8Engine *engine); - - QVariant value; -}; - -QV8ValueTypeResource::QV8ValueTypeResource(QV8Engine *engine, ObjectType objectType) -: QV8ObjectResource(engine), objectType(objectType) -{ -} - -QV8ValueTypeReferenceResource::QV8ValueTypeReferenceResource(QV8Engine *engine) -: QV8ValueTypeResource(engine, Reference) -{ -} - -QV8ValueTypeCopyResource::QV8ValueTypeCopyResource(QV8Engine *engine) -: QV8ValueTypeResource(engine, Copy) -{ -} - -QV8ValueTypeWrapper::QV8ValueTypeWrapper() -: m_engine(0) -{ -} - -QV8ValueTypeWrapper::~QV8ValueTypeWrapper() -{ -} - -void QV8ValueTypeWrapper::destroy() -{ - qPersistentDispose(m_toString); - qPersistentDispose(m_constructor); - qPersistentDispose(m_toStringSymbol); -} - -static quint32 toStringHash = -1; - -void QV8ValueTypeWrapper::init(QV8Engine *engine) -{ - m_engine = engine; - m_toString = qPersistentNew<v8::Function>(v8::FunctionTemplate::New(ToString)->GetFunction()); - v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New(); - ft->InstanceTemplate()->SetNamedPropertyHandler(Getter, Setter); - ft->InstanceTemplate()->SetHasExternalResource(true); - ft->InstanceTemplate()->MarkAsUseUserObjectComparison(); - ft->InstanceTemplate()->SetAccessor(v8::String::New("toString"), ToStringGetter, 0, - m_toString, v8::DEFAULT, - v8::PropertyAttribute(v8::ReadOnly | v8::DontDelete)); - m_constructor = qPersistentNew<v8::Function>(ft->GetFunction()); - - m_toStringSymbol = qPersistentNew<v8::String>(v8::String::NewSymbol("toString")); - m_toStringString = QHashedV8String(m_toStringSymbol); - toStringHash = m_toStringString.hash(); -} - -v8::Local<v8::Object> QV8ValueTypeWrapper::newValueType(QObject *object, int property, QQmlValueType *type) -{ - // XXX NewInstance() should be optimized - v8::Local<v8::Object> rv = m_constructor->NewInstance(); - QV8ValueTypeReferenceResource *r = new QV8ValueTypeReferenceResource(m_engine); - r->type = type; r->object = object; r->property = property; - rv->SetExternalResource(r); - return rv; -} - -v8::Local<v8::Object> QV8ValueTypeWrapper::newValueType(const QVariant &value, QQmlValueType *type) -{ - // XXX NewInstance() should be optimized - v8::Local<v8::Object> rv = m_constructor->NewInstance(); - QV8ValueTypeCopyResource *r = new QV8ValueTypeCopyResource(m_engine); - r->type = type; r->value = value; - rv->SetExternalResource(r); - return rv; -} - -static bool readReferenceValue(QV8ValueTypeReferenceResource *reference) -{ - // A reference resource may be either a "true" reference (eg, to a QVector3D property) - // or a "variant" reference (eg, to a QVariant property which happens to contain a value-type). - QMetaProperty writebackProperty = reference->object->metaObject()->property(reference->property); - if (writebackProperty.userType() == QMetaType::QVariant) { - // variant-containing-value-type reference - QVariant variantReferenceValue; - reference->type->readVariantValue(reference->object, reference->property, &variantReferenceValue); - int variantReferenceType = variantReferenceValue.userType(); - if (variantReferenceType != reference->type->userType()) { - // This is a stale VariantReference. That is, the variant has been - // overwritten with a different type in the meantime. - // We need to modify this reference to the updated value type, if - // possible, or return false if it is not a value type. - if (QQmlValueTypeFactory::isValueType(variantReferenceType)) { - reference->type = QQmlValueTypeFactory::valueType(variantReferenceType); - if (!reference->type) { - return false; - } - } else { - return false; - } - } - reference->type->setValue(variantReferenceValue); - } else { - // value-type reference - reference->type->read(reference->object, reference->property); - } - return true; -} - -bool QV8ValueTypeWrapper::isValueType(v8::Handle<v8::Object> obj) const -{ - QV8ValueTypeResource *r = v8_resource_cast<QV8ValueTypeResource>(obj); - return (r != 0); -} - -QVariant QV8ValueTypeWrapper::toVariant(v8::Handle<v8::Object> obj, int typeHint, bool *succeeded) -{ - // NOTE: obj must not be an external resource object (ie, wrapper object) - // instead, it is a normal js object which one of the value-type providers - // may know how to convert to the given type. - return QQml_valueTypeProvider()->createVariantFromJsObject(typeHint, QQmlV8Handle::fromHandle(obj), m_engine, succeeded); -} - -QVariant QV8ValueTypeWrapper::toVariant(v8::Handle<v8::Object> obj) -{ - QV8ValueTypeResource *r = v8_resource_cast<QV8ValueTypeResource>(obj); - if (r) return toVariant(r); - else return QVariant(); -} - -QVariant QV8ValueTypeWrapper::toVariant(QV8ObjectResource *r) -{ - Q_ASSERT(r->resourceType() == QV8ObjectResource::ValueTypeType); - QV8ValueTypeResource *resource = static_cast<QV8ValueTypeResource *>(r); - - if (resource->objectType == QV8ValueTypeResource::Reference) { - QV8ValueTypeReferenceResource *reference = static_cast<QV8ValueTypeReferenceResource *>(resource); - - if (reference->object && readReferenceValue(reference)) { - return reference->type->value(); - } else { - return QVariant(); - } - - } else { - Q_ASSERT(resource->objectType == QV8ValueTypeResource::Copy); - - QV8ValueTypeCopyResource *copy = static_cast<QV8ValueTypeCopyResource *>(resource); - - return copy->value; - } -} - -bool QV8ValueTypeWrapper::isEqual(QV8ObjectResource *r, const QVariant& value) -{ - Q_ASSERT(r->resourceType() == QV8ObjectResource::ValueTypeType); - QV8ValueTypeResource *resource = static_cast<QV8ValueTypeResource *>(r); - - if (resource->objectType == QV8ValueTypeResource::Reference) { - QV8ValueTypeReferenceResource *reference = static_cast<QV8ValueTypeReferenceResource *>(resource); - if (reference->object && readReferenceValue(reference)) { - return reference->type->isEqual(value); - } else { - return false; - } - } else { - Q_ASSERT(resource->objectType == QV8ValueTypeResource::Copy); - QV8ValueTypeCopyResource *copy = static_cast<QV8ValueTypeCopyResource *>(resource); - resource->type->setValue(copy->value); - if (resource->type->isEqual(value)) - return true; - return (value == copy->value); - } -} - -v8::Handle<v8::Value> QV8ValueTypeWrapper::ToStringGetter(v8::Local<v8::String> property, - const v8::AccessorInfo &info) -{ - Q_UNUSED(property); - return info.Data(); -} - -v8::Handle<v8::Value> QV8ValueTypeWrapper::ToString(const v8::Arguments &args) -{ - QV8ValueTypeResource *resource = v8_resource_cast<QV8ValueTypeResource>(args.This()); - if (resource) { - if (resource->objectType == QV8ValueTypeResource::Reference) { - QV8ValueTypeReferenceResource *reference = static_cast<QV8ValueTypeReferenceResource *>(resource); - if (reference->object && readReferenceValue(reference)) { - return resource->engine->toString(resource->type->toString()); - } else { - return v8::Undefined(); - } - } else { - Q_ASSERT(resource->objectType == QV8ValueTypeResource::Copy); - QV8ValueTypeCopyResource *copy = static_cast<QV8ValueTypeCopyResource *>(resource); - resource->type->setValue(copy->value); - return resource->engine->toString(resource->type->toString()); - } - } else { - return v8::Undefined(); - } -} - -v8::Handle<v8::Value> QV8ValueTypeWrapper::Getter(v8::Local<v8::String> property, - const v8::AccessorInfo &info) -{ - QV8ValueTypeResource *r = v8_resource_cast<QV8ValueTypeResource>(info.This()); - if (!r) return v8::Handle<v8::Value>(); - - QHashedV8String propertystring(property); - - { - // Comparing the hash first actually makes a measurable difference here, at least on x86 - quint32 hash = propertystring.hash(); - if (hash == toStringHash && - r->engine->valueTypeWrapper()->m_toStringString == propertystring) { - return r->engine->valueTypeWrapper()->m_toString; - } - } - - // Note: readReferenceValue() can change the reference->type. - if (r->objectType == QV8ValueTypeResource::Reference) { - QV8ValueTypeReferenceResource *reference = static_cast<QV8ValueTypeReferenceResource *>(r); - - if (!reference->object || !readReferenceValue(reference)) - return v8::Handle<v8::Value>(); - - } else { - Q_ASSERT(r->objectType == QV8ValueTypeResource::Copy); - - QV8ValueTypeCopyResource *copy = static_cast<QV8ValueTypeCopyResource *>(r); - - r->type->setValue(copy->value); - } - - QQmlPropertyData local; - QQmlPropertyData *result = 0; - { - QQmlData *ddata = QQmlData::get(r->type, false); - if (ddata && ddata->propertyCache) - result = ddata->propertyCache->property(propertystring, 0, 0); - else - result = QQmlPropertyCache::property(r->engine->engine(), r->type, - propertystring, 0, local); - } - - if (!result) - return v8::Handle<v8::Value>(); - - if (result->isFunction()) { - // calling a Q_INVOKABLE function of a value type - QQmlContextData *context = r->engine->callingContext(); - return r->engine->qobjectWrapper()->getProperty(r->type, propertystring, context, QV8QObjectWrapper::IgnoreRevision); - } - -#define VALUE_TYPE_LOAD(metatype, cpptype, constructor) \ - if (result->propType == metatype) { \ - cpptype v; \ - void *args[] = { &v, 0 }; \ - r->type->qt_metacall(QMetaObject::ReadProperty, result->coreIndex, args); \ - return constructor(v); \ - } - - // These four types are the most common used by the value type wrappers - VALUE_TYPE_LOAD(QMetaType::QReal, qreal, v8::Number::New); - VALUE_TYPE_LOAD(QMetaType::Int, int, v8::Integer::New); - VALUE_TYPE_LOAD(QMetaType::QString, QString, r->engine->toString); - VALUE_TYPE_LOAD(QMetaType::Bool, bool, v8::Boolean::New); - - QVariant v(result->propType, (void *)0); - void *args[] = { v.data(), 0 }; - r->type->qt_metacall(QMetaObject::ReadProperty, result->coreIndex, args); - return r->engine->fromVariant(v); -#undef VALUE_TYPE_ACCESSOR -} - -v8::Handle<v8::Value> QV8ValueTypeWrapper::Setter(v8::Local<v8::String> property, - v8::Local<v8::Value> value, - const v8::AccessorInfo &info) -{ - QV8ValueTypeResource *r = v8_resource_cast<QV8ValueTypeResource>(info.This()); - if (!r) return value; - - QByteArray propName = r->engine->toString(property).toUtf8(); - if (r->objectType == QV8ValueTypeResource::Reference) { - QV8ValueTypeReferenceResource *reference = static_cast<QV8ValueTypeReferenceResource *>(r); - QMetaProperty writebackProperty = reference->object->metaObject()->property(reference->property); - - if (!reference->object || !writebackProperty.isWritable() || !readReferenceValue(reference)) - return value; - - // we lookup the index after readReferenceValue() since it can change the reference->type. - int index = r->type->metaObject()->indexOfProperty(propName.constData()); - if (index == -1) - return value; - QMetaProperty p = r->type->metaObject()->property(index); - - QQmlBinding *newBinding = 0; - - if (value->IsFunction()) { - if (value->ToObject()->GetHiddenValue(r->engine->bindingFlagKey()).IsEmpty()) { - // assigning a JS function to a non-var-property is not allowed. - QString error = QLatin1String("Cannot assign JavaScript function to value-type property"); - v8::ThrowException(v8::Exception::Error(r->engine->toString(error))); - return value; - } - - QQmlContextData *context = r->engine->callingContext(); - v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(value); - - QQmlPropertyData cacheData; - cacheData.setFlags(QQmlPropertyData::IsWritable | - QQmlPropertyData::IsValueTypeVirtual); - cacheData.propType = reference->object->metaObject()->property(reference->property).userType(); - cacheData.coreIndex = reference->property; - cacheData.valueTypeFlags = 0; - cacheData.valueTypeCoreIndex = index; - cacheData.valueTypePropType = p.userType(); - - v8::Local<v8::StackTrace> trace = - v8::StackTrace::CurrentStackTrace(1, - (v8::StackTrace::StackTraceOptions)(v8::StackTrace::kLineNumber | - v8::StackTrace::kScriptName)); - v8::Local<v8::StackFrame> frame = trace->GetFrame(0); - int lineNumber = frame->GetLineNumber(); - int columnNumber = frame->GetColumn(); - QString url = r->engine->toString(frame->GetScriptName()); - - newBinding = new QQmlBinding(&function, reference->object, context, - url, qmlSourceCoordinate(lineNumber), qmlSourceCoordinate(columnNumber)); - newBinding->setTarget(reference->object, cacheData, context); - newBinding->setEvaluateFlags(newBinding->evaluateFlags() | - QQmlBinding::RequiresThisObject); - } - - QQmlAbstractBinding *oldBinding = - QQmlPropertyPrivate::setBinding(reference->object, reference->property, index, newBinding); - if (oldBinding) - oldBinding->destroy(); - - if (!value->IsFunction()) { - QVariant v = r->engine->toVariant(value, -1); - - if (p.isEnumType() && (QMetaType::Type)v.type() == QMetaType::Double) - v = v.toInt(); - - p.write(reference->type, v); - - if (writebackProperty.userType() == QMetaType::QVariant) { - QVariant variantReferenceValue = r->type->value(); - reference->type->writeVariantValue(reference->object, reference->property, 0, &variantReferenceValue); - } else { - reference->type->write(reference->object, reference->property, 0); - } - } - - } else { - Q_ASSERT(r->objectType == QV8ValueTypeResource::Copy); - - QV8ValueTypeCopyResource *copy = static_cast<QV8ValueTypeCopyResource *>(r); - - int index = r->type->metaObject()->indexOfProperty(propName.constData()); - if (index == -1) - return value; - - QVariant v = r->engine->toVariant(value, -1); - - r->type->setValue(copy->value); - QMetaProperty p = r->type->metaObject()->property(index); - p.write(r->type, v); - copy->value = r->type->value(); - } - - return value; -} - -QT_END_NAMESPACE diff --git a/src/qml/qml/v8/qv8valuetypewrapper_p.h b/src/qml/qml/v8/qv8valuetypewrapper_p.h deleted file mode 100644 index d22874639a..0000000000 --- a/src/qml/qml/v8/qv8valuetypewrapper_p.h +++ /dev/null @@ -1,108 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QV8VALUETYPEWRAPPER_P_H -#define QV8VALUETYPEWRAPPER_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <QtCore/qglobal.h> -#include <QtQml/qqmllist.h> -#include <private/qtqmlglobal_p.h> -#include <private/qv8_p.h> -#include <private/qhashedstring_p.h> - -QT_BEGIN_NAMESPACE - -class QV8Engine; -class QV8ObjectResource; -class QQmlValueType; -class Q_QML_PRIVATE_EXPORT QV8ValueTypeWrapper -{ -public: - QV8ValueTypeWrapper(); - ~QV8ValueTypeWrapper(); - - void init(QV8Engine *); - void destroy(); - - v8::Local<v8::Object> newValueType(QObject *, int, QQmlValueType *); - v8::Local<v8::Object> newValueType(const QVariant &, QQmlValueType *); - - bool isValueType(v8::Handle<v8::Object>) const; - - QVariant toVariant(v8::Handle<v8::Object>, int typeHint, bool *succeeded); - QVariant toVariant(v8::Handle<v8::Object>); - QVariant toVariant(QV8ObjectResource *); - - static bool isEqual(QV8ObjectResource *, const QVariant& value); - -private: - static v8::Handle<v8::Value> ToStringGetter(v8::Local<v8::String> property, - const v8::AccessorInfo &info); - static v8::Handle<v8::Value> ToString(const v8::Arguments &args); - static v8::Handle<v8::Value> Getter(v8::Local<v8::String> property, - const v8::AccessorInfo &info); - static v8::Handle<v8::Value> Setter(v8::Local<v8::String> property, - v8::Local<v8::Value> value, - const v8::AccessorInfo &info); - - QV8Engine *m_engine; - v8::Persistent<v8::Function> m_constructor; - v8::Persistent<v8::Function> m_toString; - v8::Persistent<v8::String> m_toStringSymbol; - QHashedV8String m_toStringString; -}; - -QT_END_NAMESPACE - -#endif // QV8VALUETYPEWRAPPER_P_H - - diff --git a/src/qml/qml/v8/qv8variantresource_p.h b/src/qml/qml/v8/qv8variantresource_p.h deleted file mode 100644 index 1c65861c98..0000000000 --- a/src/qml/qml/v8/qv8variantresource_p.h +++ /dev/null @@ -1,81 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QV8VARIANTRESOURCE_P_H -#define QV8VARIANTRESOURCE_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <QtCore/qglobal.h> -#include <private/qv8_p.h> -#include <private/qv8engine_p.h> -#include <private/qqmlengine_p.h> - -QT_BEGIN_NAMESPACE - -class QV8VariantResource : public QV8ObjectResource, - public QQmlEnginePrivate::ScarceResourceData -{ - V8_RESOURCE_TYPE(VariantType) - -public: - QV8VariantResource(QV8Engine *engine, const QVariant &data); - - void addVmePropertyReference(); - void removeVmePropertyReference(); - - bool m_isScarceResource; - int m_vmePropertyReferenceCount; -}; - -QT_END_NAMESPACE - -#endif // QV8VARIANTRESOURCE_P_H - diff --git a/src/qml/qml/v8/qv8variantwrapper.cpp b/src/qml/qml/v8/qv8variantwrapper.cpp deleted file mode 100644 index bea016a905..0000000000 --- a/src/qml/qml/v8/qv8variantwrapper.cpp +++ /dev/null @@ -1,279 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qv8variantwrapper_p.h" -#include "qv8variantresource_p.h" -#include "qv8engine_p.h" -#include <private/qqmlengine_p.h> - -QT_BEGIN_NAMESPACE - -QV8VariantResource::QV8VariantResource(QV8Engine *engine, const QVariant &data) -: QV8ObjectResource(engine), QQmlEnginePrivate::ScarceResourceData(data), m_isScarceResource(false), m_vmePropertyReferenceCount(0) -{ -} - -void QV8VariantResource::addVmePropertyReference() -{ - if (m_isScarceResource && ++m_vmePropertyReferenceCount == 1) { - // remove from the ep->scarceResources list - // since it is now no longer eligible to be - // released automatically by the engine. - node.remove(); - } -} - -void QV8VariantResource::removeVmePropertyReference() -{ - if (m_isScarceResource && --m_vmePropertyReferenceCount == 0) { - // and add to the ep->scarceResources list - // since it is now eligible to be released - // automatically by the engine. - QQmlEnginePrivate::get(engine->engine())->scarceResources.insert(this); - } -} - -QV8VariantWrapper::QV8VariantWrapper() -: m_engine(0) -{ -} - -QV8VariantWrapper::~QV8VariantWrapper() -{ -} - -void QV8VariantWrapper::init(QV8Engine *engine) -{ - m_engine = engine; - m_toString = qPersistentNew<v8::Function>(v8::FunctionTemplate::New(ToString)->GetFunction()); - m_valueOf = qPersistentNew<v8::Function>(v8::FunctionTemplate::New(ValueOf)->GetFunction()); - - { - v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New(); - ft->InstanceTemplate()->SetFallbackPropertyHandler(Getter, Setter); - ft->InstanceTemplate()->SetHasExternalResource(true); - ft->InstanceTemplate()->MarkAsUseUserObjectComparison(); - ft->InstanceTemplate()->SetAccessor(v8::String::New("toString"), ToStringGetter, 0, - m_toString, v8::DEFAULT, - v8::PropertyAttribute(v8::ReadOnly | v8::DontDelete)); - ft->InstanceTemplate()->SetAccessor(v8::String::New("valueOf"), ValueOfGetter, 0, - m_valueOf, v8::DEFAULT, - v8::PropertyAttribute(v8::ReadOnly | v8::DontDelete)); - m_constructor = qPersistentNew<v8::Function>(ft->GetFunction()); - } - { - m_preserve = qPersistentNew<v8::Function>(v8::FunctionTemplate::New(Preserve)->GetFunction()); - m_destroy = qPersistentNew<v8::Function>(v8::FunctionTemplate::New(Destroy)->GetFunction()); - v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New(); - ft->InstanceTemplate()->SetFallbackPropertyHandler(Getter, Setter); - ft->InstanceTemplate()->SetHasExternalResource(true); - ft->InstanceTemplate()->MarkAsUseUserObjectComparison(); - ft->InstanceTemplate()->SetAccessor(v8::String::New("preserve"), PreserveGetter, 0, - m_preserve, v8::DEFAULT, - v8::PropertyAttribute(v8::ReadOnly | v8::DontDelete)); - ft->InstanceTemplate()->SetAccessor(v8::String::New("destroy"), DestroyGetter, 0, - m_destroy, v8::DEFAULT, - v8::PropertyAttribute(v8::ReadOnly | v8::DontDelete)); - ft->InstanceTemplate()->SetAccessor(v8::String::New("toString"), ToStringGetter, 0, - m_toString, v8::DEFAULT, - v8::PropertyAttribute(v8::ReadOnly | v8::DontDelete)); - ft->InstanceTemplate()->SetAccessor(v8::String::New("valueOf"), ValueOfGetter, 0, - m_valueOf, v8::DEFAULT, - v8::PropertyAttribute(v8::ReadOnly | v8::DontDelete)); - m_scarceConstructor = qPersistentNew<v8::Function>(ft->GetFunction()); - } - -} - -void QV8VariantWrapper::destroy() -{ - qPersistentDispose(m_valueOf); - qPersistentDispose(m_toString); - qPersistentDispose(m_destroy); - qPersistentDispose(m_preserve); - qPersistentDispose(m_scarceConstructor); - qPersistentDispose(m_constructor); -} - -v8::Local<v8::Object> QV8VariantWrapper::newVariant(const QVariant &value) -{ - bool scarceResource = value.type() == QVariant::Pixmap || - value.type() == QVariant::Image; - - // XXX NewInstance() should be optimized - v8::Local<v8::Object> rv; - QV8VariantResource *r = new QV8VariantResource(m_engine, value); - - if (scarceResource) { - QQmlEnginePrivate *ep = QQmlEnginePrivate::get(m_engine->engine()); - Q_ASSERT(ep->scarceResourcesRefCount); - rv = m_scarceConstructor->NewInstance(); - r->m_isScarceResource = true; - ep->scarceResources.insert(r); - } else { - rv = m_constructor->NewInstance(); - } - - rv->SetExternalResource(r); - return rv; -} - -bool QV8VariantWrapper::isVariant(v8::Handle<v8::Value> value) -{ - return value->IsObject() && v8_resource_cast<QV8VariantResource>(value->ToObject()); -} - -QVariant QV8VariantWrapper::toVariant(v8::Handle<v8::Object> obj) -{ - QV8VariantResource *r = v8_resource_cast<QV8VariantResource>(obj); - return r?r->data:QVariant(); -} - -QVariant QV8VariantWrapper::toVariant(QV8ObjectResource *r) -{ - Q_ASSERT(r->resourceType() == QV8ObjectResource::VariantType); - return static_cast<QV8VariantResource *>(r)->data; -} - -QVariant &QV8VariantWrapper::variantValue(v8::Handle<v8::Value> value) -{ - Q_ASSERT(isVariant(value)); - QV8VariantResource *r = v8_resource_cast<QV8VariantResource>(value->ToObject()); - return static_cast<QV8VariantResource *>(r)->data; -} - -v8::Handle<v8::Value> QV8VariantWrapper::Getter(v8::Local<v8::String> /* property */, - const v8::AccessorInfo & /* info */) -{ - return v8::Handle<v8::Value>(); -} - -v8::Handle<v8::Value> QV8VariantWrapper::Setter(v8::Local<v8::String> /* property */, - v8::Local<v8::Value> value, - const v8::AccessorInfo & /* info */) -{ - return value; -} - -v8::Handle<v8::Value> QV8VariantWrapper::PreserveGetter(v8::Local<v8::String> property, - const v8::AccessorInfo &info) -{ - Q_UNUSED(property); - return info.Data(); -} - -v8::Handle<v8::Value> QV8VariantWrapper::DestroyGetter(v8::Local<v8::String> property, - const v8::AccessorInfo &info) -{ - Q_UNUSED(property); - return info.Data(); -} - -v8::Handle<v8::Value> QV8VariantWrapper::ToStringGetter(v8::Local<v8::String> property, - const v8::AccessorInfo &info) -{ - Q_UNUSED(property); - return info.Data(); -} - -v8::Handle<v8::Value> QV8VariantWrapper::ValueOfGetter(v8::Local<v8::String> property, - const v8::AccessorInfo &info) -{ - Q_UNUSED(property); - return info.Data(); -} - -v8::Handle<v8::Value> QV8VariantWrapper::Preserve(const v8::Arguments &args) -{ - QV8VariantResource *resource = v8_resource_cast<QV8VariantResource>(args.This()); - if (resource) { - resource->node.remove(); - } - return v8::Undefined(); -} - -v8::Handle<v8::Value> QV8VariantWrapper::Destroy(const v8::Arguments &args) -{ - QV8VariantResource *resource = v8_resource_cast<QV8VariantResource>(args.This()); - if (resource) { - resource->data = QVariant(); - resource->node.remove(); - } - return v8::Undefined(); -} - -v8::Handle<v8::Value> QV8VariantWrapper::ToString(const v8::Arguments &args) -{ - QV8VariantResource *resource = v8_resource_cast<QV8VariantResource>(args.This()); - if (resource) { - QString result = resource->data.toString(); - if (result.isEmpty() && !resource->data.canConvert(QVariant::String)) - result = QString::fromLatin1("QVariant(%0)").arg(QString::fromLatin1(resource->data.typeName())); - return resource->engine->toString(result); - } else { - return v8::Undefined(); - } -} - -v8::Handle<v8::Value> QV8VariantWrapper::ValueOf(const v8::Arguments &args) -{ - QV8VariantResource *resource = v8_resource_cast<QV8VariantResource>(args.This()); - if (resource) { - QVariant v = resource->data; - switch (v.type()) { - case QVariant::Invalid: - return v8::Undefined(); - case QVariant::String: - return resource->engine->toString(v.toString()); - case QVariant::Int: - case QVariant::Double: - case QVariant::UInt: - return v8::Number::New(v.toDouble()); - case QVariant::Bool: - return v8::Boolean::New(v.toBool()); - default: - break; - } - } - return args.This(); -} - -QT_END_NAMESPACE diff --git a/src/qml/qml/v8/qv8variantwrapper_p.h b/src/qml/qml/v8/qv8variantwrapper_p.h deleted file mode 100644 index 9f634b938d..0000000000 --- a/src/qml/qml/v8/qv8variantwrapper_p.h +++ /dev/null @@ -1,110 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QV8VARIANTWRAPPER_P_H -#define QV8VARIANTWRAPPER_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <QtCore/qglobal.h> -#include <QtQml/qqmllist.h> -#include <private/qv8_p.h> - -QT_BEGIN_NAMESPACE - -class QV8Engine; -class QV8ObjectResource; -class QV8VariantWrapper -{ -public: - QV8VariantWrapper(); - ~QV8VariantWrapper(); - - void init(QV8Engine *); - void destroy(); - - v8::Local<v8::Object> newVariant(const QVariant &); - bool isVariant(v8::Handle<v8::Value>); - static QVariant toVariant(v8::Handle<v8::Object>); - static QVariant toVariant(QV8ObjectResource *); - QVariant &variantValue(v8::Handle<v8::Value>); - -private: - static v8::Handle<v8::Value> Getter(v8::Local<v8::String> property, - const v8::AccessorInfo &info); - static v8::Handle<v8::Value> Setter(v8::Local<v8::String> property, - v8::Local<v8::Value> value, - const v8::AccessorInfo &info); - static v8::Handle<v8::Value> PreserveGetter(v8::Local<v8::String> property, - const v8::AccessorInfo &info); - static v8::Handle<v8::Value> DestroyGetter(v8::Local<v8::String> property, - const v8::AccessorInfo &info); - static v8::Handle<v8::Value> ToStringGetter(v8::Local<v8::String> property, - const v8::AccessorInfo &info); - static v8::Handle<v8::Value> ValueOfGetter(v8::Local<v8::String> property, - const v8::AccessorInfo &info); - static v8::Handle<v8::Value> Preserve(const v8::Arguments &args); - static v8::Handle<v8::Value> Destroy(const v8::Arguments &args); - static v8::Handle<v8::Value> ToString(const v8::Arguments &args); - static v8::Handle<v8::Value> ValueOf(const v8::Arguments &args); - - QV8Engine *m_engine; - v8::Persistent<v8::Function> m_constructor; - v8::Persistent<v8::Function> m_scarceConstructor; - v8::Persistent<v8::Function> m_preserve; - v8::Persistent<v8::Function> m_destroy; - v8::Persistent<v8::Function> m_toString; - v8::Persistent<v8::Function> m_valueOf; -}; - -QT_END_NAMESPACE - -#endif // QV8VARIANTWRAPPER_P_H - diff --git a/src/qml/qml/v8/qv8worker.cpp b/src/qml/qml/v8/qv8worker.cpp deleted file mode 100644 index 9556e146ef..0000000000 --- a/src/qml/qml/v8/qv8worker.cpp +++ /dev/null @@ -1,392 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qv8worker_p.h" - -#include <private/qqmllistmodel_p.h> -#include <private/qqmllistmodelworkeragent_p.h> - -QT_BEGIN_NAMESPACE - -// We allow the following JavaScript types to be passed between the main and -// the secondary thread: -// + undefined -// + null -// + Boolean -// + String -// + Function -// + Array -// + "Simple" Objects -// + Number -// + Date -// + RegExp -// <quint8 type><quint24 size><data> - -enum Type { - WorkerUndefined, - WorkerNull, - WorkerTrue, - WorkerFalse, - WorkerString, - WorkerFunction, - WorkerArray, - WorkerObject, - WorkerInt32, - WorkerUint32, - WorkerNumber, - WorkerDate, - WorkerRegexp, - WorkerListModel, - WorkerSequence -}; - -static inline quint32 valueheader(Type type, quint32 size = 0) -{ - return quint8(type) << 24 | (size & 0xFFFFFF); -} - -static inline Type headertype(quint32 header) -{ - return (Type)(header >> 24); -} - -static inline quint32 headersize(quint32 header) -{ - return header & 0xFFFFFF; -} - -static inline void push(QByteArray &data, quint32 value) -{ - data.append((const char *)&value, sizeof(quint32)); -} - -static inline void push(QByteArray &data, double value) -{ - data.append((const char *)&value, sizeof(double)); -} - -static inline void push(QByteArray &data, void *ptr) -{ - data.append((const char *)&ptr, sizeof(void *)); -} - -static inline void reserve(QByteArray &data, int extra) -{ - data.reserve(data.size() + extra); -} - -static inline quint32 popUint32(const char *&data) -{ - quint32 rv = *((quint32 *)data); - data += sizeof(quint32); - return rv; -} - -static inline double popDouble(const char *&data) -{ - double rv = *((double *)data); - data += sizeof(double); - return rv; -} - -static inline void *popPtr(const char *&data) -{ - void *rv = *((void **)data); - data += sizeof(void *); - return rv; -} - -// XXX TODO: Check that worker script is exception safe in the case of -// serialization/deserialization failures - -#define ALIGN(size) (((size) + 3) & ~3) -void QV8Worker::serialize(QByteArray &data, v8::Handle<v8::Value> v, QV8Engine *engine) -{ - if (v.IsEmpty()) { - } else if (v->IsUndefined()) { - push(data, valueheader(WorkerUndefined)); - } else if (v->IsNull()) { - push(data, valueheader(WorkerNull)); - } else if (v->IsTrue()) { - push(data, valueheader(WorkerTrue)); - } else if (v->IsFalse()) { - push(data, valueheader(WorkerFalse)); - } else if (v->IsString()) { - v8::Handle<v8::String> string = v->ToString(); - int length = string->Length() + 1; - if (length > 0xFFFFFF) { - push(data, valueheader(WorkerUndefined)); - return; - } - int utf16size = ALIGN(length * sizeof(uint16_t)); - - reserve(data, utf16size + sizeof(quint32)); - push(data, valueheader(WorkerString, length)); - - int offset = data.size(); - data.resize(data.size() + utf16size); - char *buffer = data.data() + offset; - - string->Write((uint16_t*)buffer); - } else if (v->IsFunction()) { - // XXX TODO: Implement passing function objects between the main and - // worker scripts - push(data, valueheader(WorkerUndefined)); - } else if (v->IsArray()) { - v8::Handle<v8::Array> array = v8::Handle<v8::Array>::Cast(v); - uint32_t length = array->Length(); - if (length > 0xFFFFFF) { - push(data, valueheader(WorkerUndefined)); - return; - } - reserve(data, sizeof(quint32) + length * sizeof(quint32)); - push(data, valueheader(WorkerArray, length)); - for (uint32_t ii = 0; ii < length; ++ii) - serialize(data, array->Get(ii), engine); - } else if (v->IsInt32()) { - reserve(data, 2 * sizeof(quint32)); - push(data, valueheader(WorkerInt32)); - push(data, (quint32)v->Int32Value()); - } else if (v->IsUint32()) { - reserve(data, 2 * sizeof(quint32)); - push(data, valueheader(WorkerUint32)); - push(data, v->Uint32Value()); - } else if (v->IsNumber()) { - reserve(data, sizeof(quint32) + sizeof(double)); - push(data, valueheader(WorkerNumber)); - push(data, v->NumberValue()); - } else if (v->IsDate()) { - reserve(data, sizeof(quint32) + sizeof(double)); - push(data, valueheader(WorkerDate)); - push(data, v8::Handle<v8::Date>::Cast(v)->NumberValue()); - } else if (v->IsRegExp()) { - v8::Handle<v8::RegExp> regexp = v8::Handle<v8::RegExp>::Cast(v); - quint32 flags = regexp->GetFlags(); - v8::Local<v8::String> source = regexp->GetSource(); - - int length = source->Length() + 1; - if (length > 0xFFFFFF) { - push(data, valueheader(WorkerUndefined)); - return; - } - int utf16size = ALIGN(length * sizeof(uint16_t)); - - reserve(data, sizeof(quint32) + utf16size); - push(data, valueheader(WorkerRegexp, flags)); - push(data, (quint32)length); - int offset = data.size(); - data.resize(data.size() + utf16size); - char *buffer = data.data() + offset; - - source->Write((uint16_t*)buffer); - } else if (v->IsObject() && !v->ToObject()->GetExternalResource()) { - v8::Handle<v8::Object> object = v->ToObject(); - v8::Local<v8::Array> properties = engine->getOwnPropertyNames(object); - quint32 length = properties->Length(); - if (length > 0xFFFFFF) { - push(data, valueheader(WorkerUndefined)); - return; - } - push(data, valueheader(WorkerObject, length)); - v8::TryCatch tc; - for (quint32 ii = 0; ii < length; ++ii) { - v8::Local<v8::String> str = properties->Get(ii)->ToString(); - serialize(data, str, engine); - - v8::Local<v8::Value> val = object->Get(str); - if (tc.HasCaught()) { - serialize(data, v8::Undefined(), engine); - tc.Reset(); - } else { - serialize(data, val, engine); - } - } - } else if (engine->isQObject(v)) { - // XXX TODO: Generalize passing objects between the main thread and worker scripts so - // that others can trivially plug in their elements. - QQmlListModel *lm = qobject_cast<QQmlListModel *>(engine->toQObject(v)); - if (lm && lm->agent()) { - QQmlListModelWorkerAgent *agent = lm->agent(); - agent->addref(); - push(data, valueheader(WorkerListModel)); - push(data, (void *)agent); - return; - } - // No other QObject's are allowed to be sent - push(data, valueheader(WorkerUndefined)); - } else { - // we can convert sequences, but not other types with external data. - if (v->IsObject()) { - v8::Handle<v8::Object> seqObj = v->ToObject(); - QV8ObjectResource *r = static_cast<QV8ObjectResource *>(seqObj->GetExternalResource()); - if (r->resourceType() == QV8ObjectResource::SequenceType) { - QVariant sequenceVariant = engine->sequenceWrapper()->toVariant(r); - if (!sequenceVariant.isNull()) { - // valid sequence. we generate a length (sequence length + 1 for the sequence type) - uint32_t seqLength = engine->sequenceWrapper()->sequenceLength(r); - uint32_t length = seqLength + 1; - if (length > 0xFFFFFF) { - push(data, valueheader(WorkerUndefined)); - return; - } - reserve(data, sizeof(quint32) + length * sizeof(quint32)); - push(data, valueheader(WorkerSequence, length)); - serialize(data, v8::Integer::New(sequenceVariant.userType()), engine); // sequence type - for (uint32_t ii = 0; ii < seqLength; ++ii) { - serialize(data, seqObj->Get(ii), engine); // sequence elements - } - - return; - } - } - } - - // not a sequence. - push(data, valueheader(WorkerUndefined)); - } -} - -v8::Handle<v8::Value> QV8Worker::deserialize(const char *&data, QV8Engine *engine) -{ - quint32 header = popUint32(data); - Type type = headertype(header); - - switch (type) { - case WorkerUndefined: - return v8::Undefined(); - case WorkerNull: - return v8::Null(); - case WorkerTrue: - return v8::True(); - case WorkerFalse: - return v8::False(); - case WorkerString: - { - quint32 size = headersize(header); - v8::Local<v8::String> string = v8::String::New((uint16_t*)data, size - 1); - data += ALIGN(size * sizeof(uint16_t)); - return string; - } - case WorkerFunction: - Q_ASSERT(!"Unreachable"); - break; - case WorkerArray: - { - quint32 size = headersize(header); - v8::Local<v8::Array> array = v8::Array::New(size); - for (quint32 ii = 0; ii < size; ++ii) { - array->Set(ii, deserialize(data, engine)); - } - return array; - } - case WorkerObject: - { - quint32 size = headersize(header); - v8::Local<v8::Object> o = v8::Object::New(); - for (quint32 ii = 0; ii < size; ++ii) { - v8::Handle<v8::Value> name = deserialize(data, engine); - v8::Handle<v8::Value> value = deserialize(data, engine); - o->Set(name, value); - } - return o; - } - case WorkerInt32: - return v8::Integer::New((qint32)popUint32(data)); - case WorkerUint32: - return v8::Integer::NewFromUnsigned(popUint32(data)); - case WorkerNumber: - return v8::Number::New(popDouble(data)); - case WorkerDate: - return v8::Date::New(popDouble(data)); - case WorkerRegexp: - { - quint32 flags = headersize(header); - quint32 length = popUint32(data); - v8::Local<v8::String> source = v8::String::New((uint16_t*)data, length - 1); - data += ALIGN(length * sizeof(uint16_t)); - return v8::RegExp::New(source, (v8::RegExp::Flags)flags); - } - case WorkerListModel: - { - void *ptr = popPtr(data); - QQmlListModelWorkerAgent *agent = (QQmlListModelWorkerAgent *)ptr; - v8::Handle<v8::Value> rv = engine->newQObject(agent); - if (rv->IsObject()) { - QQmlListModelWorkerAgent::VariantRef ref(agent); - QVariant var = qVariantFromValue(ref); - rv->ToObject()->SetHiddenValue(v8::String::New("qml::ref"), engine->fromVariant(var)); - } - agent->release(); - agent->setV8Engine(engine); - return rv; - } - case WorkerSequence: - { - bool succeeded = false; - quint32 length = headersize(header); - quint32 seqLength = length - 1; - int sequenceType = deserialize(data, engine)->Int32Value(); - v8::Local<v8::Array> array = v8::Array::New(seqLength); - for (quint32 ii = 0; ii < seqLength; ++ii) - array->Set(ii, deserialize(data, engine)); - QVariant seqVariant = engine->sequenceWrapper()->toVariant(array, sequenceType, &succeeded); - return engine->sequenceWrapper()->fromVariant(seqVariant, &succeeded); - } - } - Q_ASSERT(!"Unreachable"); - return v8::Undefined(); -} - -QByteArray QV8Worker::serialize(v8::Handle<v8::Value> value, QV8Engine *engine) -{ - QByteArray rv; - serialize(rv, value, engine); - return rv; -} - -v8::Handle<v8::Value> QV8Worker::deserialize(const QByteArray &data, QV8Engine *engine) -{ - const char *stream = data.constData(); - return deserialize(stream, engine); -} - -QT_END_NAMESPACE - diff --git a/src/qml/qml/v8/qv8worker_p.h b/src/qml/qml/v8/qv8worker_p.h deleted file mode 100644 index 113b0bb37f..0000000000 --- a/src/qml/qml/v8/qv8worker_p.h +++ /dev/null @@ -1,75 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtQml module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3.0 as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU General Public License version 3.0 requirements will be -** met: http://www.gnu.org/copyleft/gpl.html. -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QV8WORKER_P_H -#define QV8WORKER_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "qv8engine_p.h" - -QT_BEGIN_NAMESPACE - -class QV8Worker { -public: - struct SavedData { - }; - - static QByteArray serialize(v8::Handle<v8::Value>, QV8Engine *); - static v8::Handle<v8::Value> deserialize(const QByteArray &, QV8Engine *); - -private: - static void serialize(QByteArray &, v8::Handle<v8::Value>, QV8Engine *); - static v8::Handle<v8::Value> deserialize(const char *&, QV8Engine *); -}; - -QT_END_NAMESPACE - -#endif // QV8WORKER_P_H diff --git a/src/qml/qml/v8/script.pri b/src/qml/qml/v8/script.pri index 3439413f5e..f70588ec7b 100644 --- a/src/qml/qml/v8/script.pri +++ b/src/qml/qml/v8/script.pri @@ -9,13 +9,4 @@ HEADERS += \ $$PWD/qjsvalue.h \ $$PWD/qjsvalue_p.h \ $$PWD/qjsvalueiterator.h \ - $$PWD/qjsvalue_impl_p.h \ - $$PWD/qjsconverter_p.h \ - $$PWD/qjsconverter_impl_p.h \ - $$PWD/qscriptisolate_p.h \ - $$PWD/qscriptshareddata_p.h \ - $$PWD/qscripttools_p.h \ - $$PWD/qscript_impl_p.h \ - $$PWD/qscriptoriginalglobalobject_p.h \ - $$PWD/qjsvalueiterator_p.h \ - $$PWD/qjsvalueiterator_impl_p.h + $$PWD/qjsvalueiterator_p.h diff --git a/src/qml/qml/v8/v8.pri b/src/qml/qml/v8/v8.pri index 33a0ad10a1..d3edc591a7 100644 --- a/src/qml/qml/v8/v8.pri +++ b/src/qml/qml/v8/v8.pri @@ -1,44 +1,16 @@ include(script.pri) HEADERS += \ - $$PWD/qv8_p.h \ $$PWD/qv8debug_p.h \ $$PWD/qv8profiler_p.h \ - $$PWD/qv8stringwrapper_p.h \ $$PWD/qv8engine_p.h \ - $$PWD/qv8sequencewrapper_p.h \ - $$PWD/qv8sequencewrapper_p_p.h \ - $$PWD/qv8contextwrapper_p.h \ - $$PWD/qv8qobjectwrapper_p.h \ - $$PWD/qv8typewrapper_p.h \ - $$PWD/qv8listwrapper_p.h \ - $$PWD/qv8variantwrapper_p.h \ - $$PWD/qv8variantresource_p.h \ - $$PWD/qv8valuetypewrapper_p.h \ - $$PWD/qv8jsonwrapper_p.h \ - $$PWD/qv8include_p.h \ - $$PWD/qv8worker_p.h \ - $$PWD/qv8bindings_p.h \ - $$PWD/qv8engine_impl_p.h \ - $$PWD/qv8domerrors_p.h \ - $$PWD/qv8sqlerrors_p.h \ - $$PWD/qqmlbuiltinfunctions_p.h \ - $$PWD/qv8objectresource_p.h + $$PWD/qv4domerrors_p.h \ + $$PWD/qv4sqlerrors_p.h \ + $$PWD/qqmlbuiltinfunctions_p.h SOURCES += \ - $$PWD/qv8stringwrapper.cpp \ $$PWD/qv8engine.cpp \ - $$PWD/qv8sequencewrapper.cpp \ - $$PWD/qv8contextwrapper.cpp \ - $$PWD/qv8qobjectwrapper.cpp \ - $$PWD/qv8typewrapper.cpp \ - $$PWD/qv8listwrapper.cpp \ - $$PWD/qv8variantwrapper.cpp \ - $$PWD/qv8valuetypewrapper.cpp \ - $$PWD/qv8jsonwrapper.cpp \ - $$PWD/qv8include.cpp \ - $$PWD/qv8worker.cpp \ - $$PWD/qv8bindings.cpp \ - $$PWD/qv8domerrors.cpp \ - $$PWD/qv8sqlerrors.cpp \ + $$PWD/qv4domerrors.cpp \ + $$PWD/qv4sqlerrors.cpp \ $$PWD/qqmlbuiltinfunctions.cpp + |