Cleanup lots of V8 dependencies in QJS* classes

Implement a good part of QJSValue using V4.
Keep the QV8Engine for now (as it is used everywhere),
but add an ExecutionEngine pointer to it so other parts
can more easily be ported to V4.
Remove a lot of other stuff that's not required anymore.

Change-Id: Ibe2c9ab10f0ee977e0e3d05a42f526206d7b22b5
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
This commit is contained in:
Lars Knoll 2013-04-17 18:17:30 +02:00 committed by Simon Hausmann
parent 67b09aef34
commit 94eee5842a
46 changed files with 447 additions and 2141 deletions

View File

@ -41,7 +41,7 @@
#include "qv8debugservice_p.h"
#include "qqmldebugservice_p_p.h"
#include <private/qjsconverter_impl_p.h>
#include <private/qjsconverter_p.h>
#include <private/qv4compiler_p.h>
#include <private/qv8engine_p.h>

View File

@ -41,7 +41,7 @@
#include "qv8profilerservice_p.h"
#include "qqmldebugservice_p_p.h"
#include "private/qjsconverter_impl_p.h"
#include "private/qjsconverter_p.h"
#include <private/qv8profiler_p.h>
#include <QtCore/QHash>

View File

@ -42,7 +42,7 @@
#include "qqmllocale_p.h"
#include "qqmlengine_p.h"
#include <private/qqmlcontext_p.h>
#include <private/qjsconverter_impl_p.h>
#include <private/qjsconverter_p.h>
#include <QtCore/qnumeric.h>
#include <QtCore/qdatetime.h>

View File

@ -50,10 +50,7 @@
#include <private/qv8_p.h>
#include <private/qjsconverter_p.h>
#include <private/qjsconverter_impl_p.h>
#include <private/qjsvalue_impl_p.h>
#include <private/qjsvalueiterator_impl_p.h>
#include <private/qv8engine_impl_p.h>
#include <private/qv8engine_p.h>
#include <private/qqmlaccessors_p.h>
#include <private/qqmlprofilerservice_p.h>
@ -1286,7 +1283,7 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks,
} else {
QV8Engine *v8engine = QQmlEnginePrivate::get(context->engine)->v8engine();
new (output.gethandleptr()) v8::Handle<v8::Value>(
QJSValuePrivate::get(tmp)->asV8Value(v8engine));
v8::Value::fromVmValue(QJSValuePrivate::get(tmp)->value));
V8HANDLE_REGISTER(instr->unaryop.output);
}
}

View File

@ -768,6 +768,16 @@ void DatePrototype::init(ExecutionContext *ctx, const Value &ctor)
defineDefaultProperty(ctx, QStringLiteral("toJSON"), method_toJSON, 1);
}
double DatePrototype::toJSDate(const QDateTime &dateTime)
{
return FromDateTime(dateTime);
}
QDateTime DatePrototype::toQDateTime(double d)
{
return ToDateTime(d, Qt::LocalTime);
}
double DatePrototype::getThisDate(ExecutionContext *ctx)
{
if (DateObject *thisObject = ctx->thisObject.asDateObject())

View File

@ -47,6 +47,8 @@
QT_BEGIN_NAMESPACE
class QDateTime;
namespace QQmlJS {
namespace VM {
@ -71,6 +73,9 @@ struct DatePrototype: DateObject
DatePrototype(ExecutionEngine *engine): DateObject(engine, Value::fromDouble(qSNaN())) {}
void init(ExecutionContext *ctx, const Value &ctor);
static double toJSDate(const QDateTime &dateTime);
static QDateTime toQDateTime(double d);
static double getThisDate(ExecutionContext *ctx);
static Value method_parse(SimpleCallContext *ctx);

View File

@ -53,6 +53,8 @@
QT_BEGIN_NAMESPACE
class QJSEngine;
namespace QQmlJS {
namespace Debugging {
@ -123,6 +125,8 @@ struct Q_QML_EXPORT ExecutionEngine
VM::Function *globalCode;
QJSEngine *publicEngine;
Value objectCtor;
Value stringCtor;
Value numberCtor;

View File

@ -38,8 +38,8 @@
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QV4IR_P_H
#define QV4IR_P_H
#ifndef QV4JSIR_P_H
#define QV4JSIR_P_H
//
// W A R N I N G

View File

@ -46,7 +46,7 @@
#endif // QMLJS_LLVM_RUNTIME
#include <cmath>
#if !defined(QMLJS_LLVM_RUNTIME) && COMPILER(GCC) && (CPU(X86_64) || CPU(X86))
#if !defined(QMLJS_LLVM_RUNTIME) && defined(Q_CC_GCC) && defined(Q_PROCESSOR_X86)
#define QMLJS_INLINE_MATH
#define QMLJS_READONLY __attribute((const))
#endif

View File

@ -434,10 +434,9 @@ void __qmljs_inplace_ushr_member(ExecutionContext *ctx, const Value &base, Strin
o->inplaceBinOp(ctx, __qmljs_ushr, name, rhs);
}
double __qmljs_string_to_number(const String *string)
double __qmljs_string_to_number(const QString &string)
{
QString s = string->toQString();
s = s.trimmed();
QString s = string.trimmed();
if (s.startsWith(QLatin1String("0x")) || s.startsWith(QLatin1String("0X")))
return s.toLong(0, 16);
bool ok;

View File

@ -153,7 +153,7 @@ VM::Function *__qmljs_register_function(ExecutionContext *ctx, String *name,
// strings
double __qmljs_string_to_number(const String *string);
double __qmljs_string_to_number(const QString &s);
Value __qmljs_string_from_number(ExecutionContext *ctx, double number);
String *__qmljs_string_concat(ExecutionContext *ctx, String *first, String *second);
@ -305,7 +305,7 @@ inline double __qmljs_to_number(const Value &value)
case Value::Integer_Type:
return value.int_32;
case Value::String_Type:
return __qmljs_string_to_number(value.stringValue());
return __qmljs_string_to_number(value.stringValue()->toQString());
case Value::Object_Type: {
Value prim = __qmljs_to_primitive(value, NUMBER_HINT);
return __qmljs_to_number(prim);

View File

@ -183,7 +183,7 @@ uint String::toUInt(bool *ok) const
return stringHash;
// ### this conversion shouldn't be required
double d = __qmljs_string_to_number(this);
double d = __qmljs_string_to_number(toQString());
uint l = (uint)d;
if (d == l)
return l;

View File

@ -1963,6 +1963,11 @@ void Isolate::setException(const VM::Value &ex)
}
}
ExecutionEngine *Isolate::GetEngine()
{
return Isolate::GetCurrent()->GetCurrentContext()->GetEngine();
}
Isolate *Isolate::GetCurrent()
{
if (!currentIsolate.hasLocalData())

View File

@ -2289,6 +2289,8 @@ class V8EXPORT Isolate {
Context *GetCurrentContext() { return m_contextStack.top(); }
void setException(const QQmlJS::VM::Value &ex);
static QQmlJS::VM::ExecutionEngine *GetEngine();
private:
friend class Context;
friend class TryCatch;

View File

@ -169,7 +169,7 @@ Value Value::property(ExecutionContext *ctx, String *name) const
PersistentValue::PersistentValue(ExecutionEngine *e, const Value &val)
: d(PersistentValuePrivate::create(e, val))
: d(new PersistentValuePrivate(e, val))
{
}
@ -195,14 +195,23 @@ PersistentValue::~PersistentValue()
d->deref();
}
PersistentValuePrivate *PersistentValuePrivate::create(ExecutionEngine *e, const Value &v)
PersistentValuePrivate::PersistentValuePrivate(const Value &v)
: value(v)
, refcount(1)
, engine(0)
, next(0)
{
PersistentValuePrivate *d = new PersistentValuePrivate;
d->engine = e;
d->next = e->memoryManager->m_persistentValues;
e->memoryManager->m_persistentValues = d;
d->value = v;
d->refcount = 1;
assert(!v.asManaged());
}
PersistentValuePrivate::PersistentValuePrivate(ExecutionEngine *e, const Value &v)
: value(v)
, refcount(1)
, engine(e)
, next(engine->memoryManager->m_persistentValues)
{
engine->memoryManager->m_persistentValues = this;
}
void PersistentValuePrivate::deref()

View File

@ -48,7 +48,7 @@
#include <QtCore/QDebug>
#include "qv4managed_p.h"
#include <wtf/MathExtras.h>
//#include <wtf/MathExtras.h>
QT_BEGIN_NAMESPACE
@ -546,12 +546,19 @@ inline Value Managed::call(ExecutionContext *context, const Value &thisObject, V
struct PersistentValuePrivate
{
PersistentValuePrivate()
: value(Value::undefinedValue())
, refcount(1)
, engine(0)
, next(0)
{}
PersistentValuePrivate(ExecutionEngine *e, const Value &v);
PersistentValuePrivate(const Value &v);
Value value;
int refcount;
ExecutionEngine *engine;
PersistentValuePrivate *next;
static PersistentValuePrivate *create(ExecutionEngine *e, const Value &v);
void ref() { ++refcount; }
void deref();
};

View File

@ -147,23 +147,6 @@ QString QJSConverter::toString(double value)
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.

View File

@ -65,45 +65,43 @@ QT_BEGIN_NAMESPACE
*/
class QJSConverter {
public:
static inline quint32 toArrayIndex(const QString& string);
static 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);
static QString toString(v8::Handle<v8::String> jsString);
static v8::Local<v8::String> toString(const QString& string);
static 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);
static 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);
static 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);
static 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);
static QStringList toStringList(v8::Handle<v8::Array> jsArray);
// Converts a JS Date to a QDateTime.
static inline QDateTime toDateTime(v8::Handle<v8::Date> jsDate);
static QDateTime toDateTime(v8::Handle<v8::Date> jsDate);
// Converts a QDateTime to a JS Date.
static inline v8::Local<v8::Value> toDateTime(const QDateTime &dt);
static v8::Local<v8::Value> toDateTime(const QDateTime &dt);
};
QT_END_NAMESPACE

View File

@ -44,7 +44,6 @@
#include "qjsvalue.h"
#include "qjsvalue_p.h"
#include "qscriptisolate_p.h"
#include "qscript_impl_p.h"
#include "qv8engine_p.h"
#include <QtCore/qdatetime.h>
@ -63,6 +62,8 @@
#include <qwaitcondition.h>
#include <private/qqmlglobal_p.h>
#include <private/qjsconverter_impl_p.h>
#undef Q_D
#undef Q_Q
#define Q_D(blah)
@ -257,7 +258,7 @@ QJSValue QJSEngine::evaluate(const QString& program, const QString& fileName, in
Q_D(QJSEngine);
QScriptIsolate api(d, QScriptIsolate::NotNullEngine);
v8::HandleScope handleScope;
return QJSValuePrivate::get(d->evaluate(program, fileName, qmlSourceCoordinate(lineNumber)));
return d->evaluate(program, fileName, qmlSourceCoordinate(lineNumber));
}
/*!
@ -273,7 +274,8 @@ QJSValue QJSEngine::newObject()
Q_D(QJSEngine);
QScriptIsolate api(d, QScriptIsolate::NotNullEngine);
v8::HandleScope handleScope;
return QJSValuePrivate::get(new QJSValuePrivate(d, v8::Object::New()));
QQmlJS::VM::ExecutionEngine *engine = d->m_v4Engine;
return new QJSValuePrivate(engine, QQmlJS::VM::Value::fromObject(engine->newObject()));
}
/*!
@ -354,51 +356,52 @@ 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();
QQmlJS::VM::ExecutionEngine *e = vp->engine;
QV8Engine *engine = e ? QV8Engine::get(e->publicEngine) : 0;
if (engine) {
QScriptIsolate api(engine, QScriptIsolate::NotNullEngine);
v8::HandleScope handleScope;
return engine->metaTypeFromJS(*vp, type, ptr);
return engine->metaTypeFromJS(v8::Value::fromVmValue(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) = vp->value.toString(engine->m_v4Engine->current)->toQString();
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;

View File

@ -39,14 +39,18 @@
**
****************************************************************************/
#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 "qv4v8_p.h"
/*!
\since 5.0
@ -114,11 +118,18 @@
QT_BEGIN_NAMESPACE
using namespace QQmlJS::VM;
/*!
Constructs a new QJSValue with a boolean \a value.
*/
QJSValue::QJSValue(bool value)
: d_ptr(new QJSValuePrivate(value))
: d(new QJSValuePrivate(Value::fromBoolean(value)))
{
}
QJSValue::QJSValue(QJSValuePrivate *dd)
: d(dd)
{
}
@ -126,7 +137,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(Value::fromInt32(value)))
{
}
@ -134,7 +145,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(Value::fromUInt32(value)))
{
}
@ -142,7 +153,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(Value::fromDouble(value)))
{
}
@ -150,7 +161,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 +169,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(value == UndefinedValue ? Value::undefinedValue() : Value::nullValue()))
{
}
@ -166,7 +177,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,29 +186,11 @@ 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.
@ -206,8 +199,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 +209,7 @@ QJSValue::QJSValue(const QJSValue& other)
*/
QJSValue::~QJSValue()
{
d->deref();
}
/*!
@ -225,9 +220,7 @@ QJSValue::~QJSValue()
*/
bool QJSValue::isBool() const
{
Q_D(const QJSValue);
QScriptIsolate api(d->engine());
return d->isBool();
return d->value.isBoolean();
}
/*!
@ -238,9 +231,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 +240,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 +251,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 +260,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 +269,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 +281,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 +295,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 +306,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 +317,8 @@ bool QJSValue::isCallable() const
*/
bool QJSValue::isVariant() const
{
Q_D(const QJSValue);
QScriptIsolate api(d->engine());
return d->isVariant();
// ###
return false;
}
/*!
@ -358,9 +335,10 @@ bool QJSValue::isVariant() const
*/
QString QJSValue::toString() const
{
Q_D(const QJSValue);
QScriptIsolate api(d->engine());
return d->toString();
if (!d->engine)
// ###
return QString();
return d->value.toString(d->engine->current)->toQString();
}
/*!
@ -377,9 +355,7 @@ QString QJSValue::toString() const
*/
double QJSValue::toNumber() const
{
Q_D(const QJSValue);
QScriptIsolate api(d->engine());
return d->toNumber();
return d->value.toNumber();
}
/*!
@ -396,9 +372,7 @@ double QJSValue::toNumber() const
*/
bool QJSValue::toBool() const
{
Q_D(const QJSValue);
QScriptIsolate api(d->engine());
return d->toBool();
return d->value.toBoolean();
}
/*!
@ -415,9 +389,7 @@ bool QJSValue::toBool() const
*/
qint32 QJSValue::toInt() const
{
Q_D(const QJSValue);
QScriptIsolate api(d->engine());
return d->toInt32();
return d->value.toInt32();
}
/*!
@ -434,9 +406,7 @@ qint32 QJSValue::toInt() const
*/
quint32 QJSValue::toUInt() const
{
Q_D(const QJSValue);
QScriptIsolate api(d->engine());
return d->toUInt32();
return d->value.toUInt32();
}
/*!
@ -463,9 +433,8 @@ quint32 QJSValue::toUInt() const
*/
QVariant QJSValue::toVariant() const
{
Q_D(const QJSValue);
QScriptIsolate api(d->engine());
return d->toVariant();
// ###
return QVariant();
}
/*!
@ -485,9 +454,25 @@ 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> arguments(args.length());
for (int i = 0; i < args.size(); ++i)
arguments[i] = args.at(i).d->getValue(engine);
Value result;
try {
result = f->call(d->engine->current, Value::fromObject(d->engine->globalObject), arguments.data(), arguments.size());
} catch (Exception &e) {
result = e.value();
}
return new QJSValuePrivate(engine, result);
}
/*!
@ -512,9 +497,25 @@ 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);
QVarLengthArray<Value> arguments(args.length());
for (int i = 0; i < args.size(); ++i)
arguments[i] = args.at(i).d->getValue(engine);
Value result;
try {
result = f->call(d->engine->current, instance.d->getValue(engine), arguments.data(), arguments.size());
} catch (Exception &e) {
result = e.value();
}
return new QJSValuePrivate(engine, result);
}
/*!
@ -537,9 +538,25 @@ 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> arguments(args.length());
for (int i = 0; i < args.size(); ++i)
arguments[i] = args.at(i).d->getValue(engine);
Value result;
try {
result = f->construct(d->engine->current, arguments.data(), arguments.size());
} catch (Exception &e) {
result = e.value();
}
return new QJSValuePrivate(engine, result);
}
#ifdef QT_DEPRECATED
@ -553,12 +570,8 @@ QJSValue QJSValue::callAsConstructor(const QJSValueList &args)
*/
QJSEngine* QJSValue::engine() const
{
Q_D(const QJSValue);
QScriptIsolate api(d->engine());
QV8Engine* engine = d->engine();
if (engine)
return QV8Engine::get(engine);
return 0;
if (d->engine)
return d->engine->publicEngine;
}
#endif // QT_DEPRECATED
@ -572,9 +585,10 @@ 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();
return new QJSValuePrivate(d->engine, Value::fromObject(o->prototype));
}
/*!
@ -590,9 +604,13 @@ 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;
Object *p = prototype.d->value.asObject();
if (!p)
return;
o->prototype = p;
}
/*!
@ -604,8 +622,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 +655,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 +682,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 +700,13 @@ 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();
String *s = d->engine->newIdentifier(name);
QQmlJS::VM::Value v = o->get(d->engine->current, s);
return new QJSValuePrivate(d->engine, v);
}
/*!
@ -704,9 +723,12 @@ 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();
QQmlJS::VM::Value v = o->getIndexed(d->engine->current, arrayIndex);
return new QJSValuePrivate(d->engine, v);
}
/*!
@ -722,9 +744,12 @@ 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;
String *s = d->engine->newIdentifier(name);
o->put(d->engine->current, s, value.d->value);
}
/*!
@ -741,9 +766,11 @@ 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;
o->putIndexed(d->engine->current, arrayIndex, value.d->value);
}
/*!
@ -768,9 +795,12 @@ 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;
String *s = d->engine->newIdentifier(name);
return o->deleteProperty(d->engine->current, s);
}
/*!
@ -781,9 +811,12 @@ 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;
String *s = d->engine->newIdentifier(name);
return o->__hasProperty__(s);
}
/*!
@ -794,9 +827,12 @@ 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;
String *s = d->engine->newIdentifier(name);
return o->__getOwnProperty__(s);
}
/*!
@ -811,9 +847,7 @@ bool QJSValue::hasOwnProperty(const QString &name) const
*/
QObject *QJSValue::toQObject() const
{
Q_D(const QJSValue);
QScriptIsolate api(d->engine());
return d->toQObject();
// ###
}
/*!
@ -825,9 +859,10 @@ QObject *QJSValue::toQObject() const
*/
QDateTime QJSValue::toDateTime() const
{
Q_D(const QJSValue);
QScriptIsolate api(d->engine());
return d->toDataTime();
QQmlJS::VM::DateObject *date = d->value.asDateObject();
if (!date)
return QDateTime();
return QQmlJS::VM::DatePrototype::toQDateTime(date->value.toNumber());
}
/*!
@ -838,9 +873,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 +882,7 @@ bool QJSValue::isDate() const
*/
bool QJSValue::isRegExp() const
{
Q_D(const QJSValue);
QScriptIsolate api(d->engine());
return d->isRegExp();
return d->value.asRegExpObject();
}
/*!
@ -865,9 +896,7 @@ bool QJSValue::isRegExp() const
*/
bool QJSValue::isQObject() const
{
Q_D(const QJSValue);
QScriptIsolate api(d->engine());
return d->isQObject();
// ###
}
/*!
@ -893,7 +922,7 @@ bool QJSValue::isQObject() const
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 v8::Local<v8::Value>::New(v8::Value::fromVmValue(d->value));
}
QT_END_NAMESPACE

View File

@ -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

View File

@ -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.get())->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.get())->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.get())->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.get()));
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().get()));
} 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.get()));
}
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.get())->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.get())->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

View File

@ -53,161 +53,48 @@
#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>
QT_BEGIN_NAMESPACE
class QV8Engine;
/*!
\internal
\class QJSValuePrivate
*/
class QJSValuePrivate
: public QSharedData
class QJSValuePrivate : public QQmlJS::VM::PersistentValuePrivate
{
public:
enum PropertyFlag {
ReadOnly = 0x00000001,
Undeletable = 0x00000002,
SkipInEnumeration = 0x00000004
};
Q_DECLARE_FLAGS(PropertyFlags, PropertyFlag)
QJSValuePrivate(QQmlJS::VM::ExecutionEngine *e, const QQmlJS::VM::Value &v)
: PersistentValuePrivate(e, v)
, string(QString())
{}
QJSValuePrivate(const QQmlJS::VM::Value &v)
: PersistentValuePrivate(v)
, string(QString())
{}
QJSValuePrivate(const QString &s)
: PersistentValuePrivate()
, string(s)
{
value = QQmlJS::VM::Value::fromString(&string);
}
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();
QQmlJS::VM::Value getValue(QQmlJS::VM::ExecutionEngine *e) {
if (value.asString() == &string) {
engine = e;
value = QQmlJS::VM::Value::fromString(e->newString(string.toQString()));
}
return value;
}
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);
static QJSValuePrivate *get(const QJSValue &v) { return v.d; }
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;
QQmlJS::VM::String string;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QJSValuePrivate::PropertyFlags)
QT_END_NAMESPACE
#endif

View File

@ -42,11 +42,6 @@
#include "qjsvalueiterator.h"
#include "qjsvalueiterator_p.h"
#include "qscriptisolate_p.h"
#include "qjsvalue_p.h"
#include "qv8engine_p.h"
#include "qscript_impl_p.h"
QT_BEGIN_NAMESPACE
/*!
@ -84,14 +79,18 @@ QT_BEGIN_NAMESPACE
first property).
*/
QJSValueIterator::QJSValueIterator(const QJSValue& object)
: d_ptr(new QJSValueIteratorPrivate(QJSValuePrivate::get(object)))
{}
: d_ptr(0)
{
// ###
}
/*!
Destroys the iterator.
*/
QJSValueIterator::~QJSValueIterator()
{}
{
// ###
}
/*!
Returns true if there is at least one item ahead of the iterator
@ -102,9 +101,7 @@ QJSValueIterator::~QJSValueIterator()
*/
bool QJSValueIterator::hasNext() const
{
Q_D(const QJSValueIterator);
QScriptIsolate api(d->engine());
return d->hasNext();
// ###
}
/*!
@ -120,9 +117,7 @@ bool QJSValueIterator::hasNext() const
*/
bool QJSValueIterator::next()
{
Q_D(QJSValueIterator);
QScriptIsolate api(d->engine());
return d->next();
// ###
}
/*!
@ -133,9 +128,7 @@ bool QJSValueIterator::next()
*/
QString QJSValueIterator::name() const
{
Q_D(const QJSValueIterator);
QScriptIsolate api(d->engine());
return d_ptr->name();
// ###
}
@ -147,9 +140,7 @@ QString QJSValueIterator::name() const
*/
QJSValue QJSValueIterator::value() const
{
Q_D(const QJSValueIterator);
QScriptIsolate api(d->engine());
return QJSValuePrivate::get(d->value());
// ###
}
@ -160,10 +151,7 @@ QJSValue QJSValueIterator::value() const
*/
QJSValueIterator& QJSValueIterator::operator=(QJSValue& object)
{
Q_D(QJSValueIterator);
QScriptIsolate api(d->engine());
d_ptr.reset(new QJSValueIteratorPrivate(QJSValuePrivate::get(object)));
return *this;
// ###
}
QT_END_NAMESPACE

View File

@ -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

View File

@ -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

View File

@ -42,10 +42,7 @@
#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"
QT_BEGIN_NAMESPACE
@ -54,30 +51,6 @@ 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;
};

View File

@ -47,7 +47,7 @@
#include <private/qqmlstringconverters_p.h>
#include <private/qqmllocale_p.h>
#include <private/qv8engine_p.h>
#include <private/qjsconverter_impl_p.h>
#include <private/qjsconverter_p.h>
#include <private/qv8profilerservice_p.h>
#include <private/qqmlprofilerservice_p.h>

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -55,14 +55,17 @@
#include <private/qqmlglobal_p.h>
#include <private/qqmlmemoryprofiler_p.h>
#include <private/qqmlplatform_p.h>
#include <private/qjsconverter_p.h>
#include "qscript_impl_p.h"
#include "qv8domerrors_p.h"
#include "qv8sqlerrors_p.h"
#include <QtCore/qjsonarray.h>
#include <QtCore/qjsonobject.h>
#include <QtCore/qjsonvalue.h>
#include <QtCore/qdatetime.h>
#include <private/qv8engine_impl_p.h>
Q_DECLARE_METATYPE(QList<int>)
@ -144,9 +147,11 @@ QV8Engine::QV8Engine(QJSEngine* qq, ContextOwnership ownership)
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);
m_v4Engine = v8::Isolate::GetEngine();
m_v4Engine->publicEngine = q;
v8::V8::SetUserObjectComparisonCallbackFunction(ObjectComparisonCallback);
QV8GCCallback::registerGcPrologueCallback();
m_strongReferencer = qPersistentNew(v8::Object::New());
@ -184,8 +189,6 @@ QV8Engine::~QV8Engine()
qPersistentDispose(m_freezeObject);
qPersistentDispose(m_getOwnPropertyNames);
invalidateAllValues();
qPersistentDispose(m_strongReferencer);
m_jsonWrapper.destroy();
@ -200,8 +203,6 @@ QV8Engine::~QV8Engine()
qPersistentDispose(m_bindingFlagKey);
m_originalGlobalObject.destroy();
if (m_ownsV8Context)
qPersistentDispose(m_context);
}
@ -411,8 +412,10 @@ v8::Handle<v8::Value> QV8Engine::fromVariant(const QVariant &variant)
} 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);
valuep->engine = m_v4Engine;
return v8::Local<v8::Value>::New(v8::Value::fromVmValue(valuep->getValue(valuep->engine)));
// if (valuep->assignEngine(this))
// return v8::Local<v8::Value>::New(*valuep);
} else if (type == qMetaTypeId<QList<QObject *> >()) {
// XXX Can this be made more by using Array as a prototype and implementing
// directly against QList<QObject*>?
@ -1073,7 +1076,7 @@ v8::Handle<v8::Value> QV8Engine::metaTypeToJS(int type, const void *data)
break;
default:
if (type == qMetaTypeId<QJSValue>()) {
return QJSValuePrivate::get(*reinterpret_cast<const QJSValue*>(data))->asV8Value(this);
return v8::Value::fromVmValue(QJSValuePrivate::get(*reinterpret_cast<const QJSValue*>(data))->value);
} else {
QByteArray typeName = QMetaType::typeName(type);
if (typeName.endsWith('*') && !*reinterpret_cast<void* const *>(data)) {
@ -1251,7 +1254,7 @@ bool QV8Engine::metaTypeFromJS(v8::Handle<v8::Value> value, int type, void *data
*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.get()->vmValue()));
return true;
}
@ -1385,7 +1388,7 @@ 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)
QJSValue QV8Engine::evaluate(v8::Handle<v8::Script> script, v8::TryCatch& tryCatch)
{
v8::HandleScope handleScope;
@ -1393,9 +1396,9 @@ QScriptPassPointer<QJSValuePrivate> QV8Engine::evaluate(v8::Handle<v8::Script> s
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 QJSValue();
}
return new QJSValuePrivate(this, exception);
return new QJSValuePrivate(m_v4Engine, exception.get()->vmValue());
}
v8::Handle<v8::Value> result;
result = script->Run();
@ -1405,21 +1408,21 @@ QScriptPassPointer<QJSValuePrivate> QV8Engine::evaluate(v8::Handle<v8::Script> s
//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(m_v4Engine, exception.get()->vmValue());
}
return new QJSValuePrivate(this, result);
return new QJSValuePrivate(m_v4Engine, result.get()->vmValue());
}
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));
return QJSValue();
return new QJSValuePrivate(m_v4Engine, value.get()->vmValue());
}
QScriptPassPointer<QJSValuePrivate> QV8Engine::newArray(uint length)
QJSValue QV8Engine::newArray(uint length)
{
return new QJSValuePrivate(this, v8::Array::New(length));
return new QJSValuePrivate(m_v4Engine, v8::Array::New(length).get()->vmValue());
}
void QV8Engine::startTimer(const QString &timerName)

View File

@ -57,102 +57,92 @@
#include "qjsvalue_p.h"
#include "qjsconverter_p.h"
#include "qjsvalueiterator_p.h"
#include "qv4errorobject_p.h"
QT_BEGIN_NAMESPACE
inline v8::Handle<v8::Value> QV8Engine::makeJSValue(bool value)
v8::Handle<v8::Value> QV8Engine::makeJSValue(bool value)
{
return value ? v8::True() : v8::False();
}
inline v8::Local<v8::Value> QV8Engine::makeJSValue(int value)
v8::Local<v8::Value> QV8Engine::makeJSValue(int value)
{
return v8::Integer::New(value);
}
inline v8::Local<v8::Value> QV8Engine::makeJSValue(uint value)
v8::Local<v8::Value> QV8Engine::makeJSValue(uint value)
{
return v8::Integer::NewFromUnsigned(value);
}
inline v8::Local<v8::Value> QV8Engine::makeJSValue(double value)
v8::Local<v8::Value> QV8Engine::makeJSValue(double value)
{
return v8::Number::New(value);
}
inline v8::Handle<v8::Value> QV8Engine::makeJSValue(QJSValue::SpecialValue value) {
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)
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();
}
};
//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);
}
//void QV8Engine::registerValue(QJSValuePrivate *data)
//{
// m_values.insert(data);
//}
inline void QV8Engine::unregisterValue(QJSValuePrivate *data)
{
m_values.remove(data);
}
//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());
}
//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);
}
//void QV8Engine::registerValueIterator(QJSValueIteratorPrivate *data)
//{
// m_valueIterators.insert(data);
//}
inline void QV8Engine::unregisterValueIterator(QJSValueIteratorPrivate *data)
{
m_valueIterators.remove(data);
}
//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());
}
//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)
QJSValue QV8Engine::evaluate(const QString& program, const QString& fileName, quint16 lineNumber)
{
v8::TryCatch tryCatch;
v8::ScriptOrigin scriptOrigin(QJSConverter::toString(fileName), v8::Integer::New(lineNumber - 1));
@ -161,8 +151,8 @@ QScriptPassPointer<QJSValuePrivate> QV8Engine::evaluate(const QString& program,
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);
QQmlJS::VM::Object *error = m_v4Engine->newSyntaxErrorObject(m_v4Engine->current, 0);
return new QJSValuePrivate(m_v4Engine, QQmlJS::VM::Value::fromObject(error));
}
return evaluate(script, tryCatch);
}

View File

@ -65,10 +65,8 @@
#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>
@ -95,6 +93,11 @@ inline uint qHash(const v8::Handle<v8::Object> &object, uint seed = 0)
QT_BEGIN_NAMESPACE
namespace QQmlJS {
namespace VM {
class ExecutionEngine;
}
}
// Uncomment the following line to enable global handle debugging. When enabled, all the persistent
// handles allocated using qPersistentNew() (or registered with qPersistentRegsiter()) and disposed
@ -247,10 +250,13 @@ public:
class Q_QML_PRIVATE_EXPORT QV8Engine
{
friend class QJSEngine;
typedef QSet<v8::Handle<v8::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 QQmlJS::VM::ExecutionEngine *getV4(QJSEngine *q) { return q->handle()->m_v4Engine; }
static QQmlJS::VM::ExecutionEngine *getV4(QV8Engine *d) { return d->m_v4Engine; }
enum ContextOwnership {
AdoptCurrentContext,
@ -272,13 +278,13 @@ public:
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 registerValue(QJSValuePrivate *data);
// inline void unregisterValue(QJSValuePrivate *data);
// inline void invalidateAllValues();
inline void registerValueIterator(QJSValueIteratorPrivate *data);
inline void unregisterValueIterator(QJSValueIteratorPrivate *data);
inline void invalidateAllIterators();
// inline void registerValueIterator(QJSValueIteratorPrivate *data);
// inline void unregisterValueIterator(QJSValueIteratorPrivate *data);
// inline void invalidateAllIterators();
QV8ContextWrapper *contextWrapper() { return &m_contextWrapper; }
QV8QObjectWrapper *qobjectWrapper() { return &m_qobjectWrapper; }
@ -296,7 +302,6 @@ 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);
@ -370,17 +375,17 @@ 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);
v8::Handle<v8::Value> makeJSValue(bool value);
v8::Local<v8::Value> makeJSValue(int value);
v8::Local<v8::Value> makeJSValue(uint value);
v8::Local<v8::Value> makeJSValue(double value);
v8::Handle<v8::Value> makeJSValue(QJSValue::SpecialValue value);
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);
QJSValue evaluate(const QString &program, const QString &fileName = QString(), quint16 lineNumber = 1);
QJSValue evaluate(v8::Handle<v8::Script> script, v8::TryCatch& tryCatch);
QScriptPassPointer<QJSValuePrivate> newArray(uint length);
QJSValue newArray(uint length);
v8::Local<v8::Object> newVariant(const QVariant &variant);
v8::Local<v8::Array> variantListToJS(const QVariantList &lst);
@ -450,9 +455,11 @@ public:
protected:
QJSEngine* q;
QQmlEngine *m_engine;
QQmlJS::VM::ExecutionEngine *m_v4Engine;
bool m_ownsV8Context;
v8::Persistent<v8::Context> m_context;
QScriptOriginalGlobalObject m_originalGlobalObject;
v8::Persistent<v8::String> m_bindingFlagKey;
@ -497,10 +504,10 @@ private:
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;
// typedef QIntrusiveList<QJSValuePrivate, &QJSValuePrivate::m_node> ValueList;
// ValueList m_values;
// typedef QIntrusiveList<QJSValueIteratorPrivate, &QJSValueIteratorPrivate::m_node> ValueIteratorList;
// ValueIteratorList m_valueIterators;
Q_DISABLE_COPY(QV8Engine)
};

View File

@ -41,7 +41,7 @@
#include "qv8jsonwrapper_p.h"
#include "qv8engine_p.h"
#include "qjsconverter_impl_p.h"
#include "qjsconverter_p.h"
QT_BEGIN_NAMESPACE

View File

@ -49,7 +49,6 @@
#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>
@ -434,7 +433,7 @@ static v8::Handle<v8::Value> LoadProperty(QV8Engine *engine, QObject *object,
} else if (property.propType == qMetaTypeId<QJSValue>()) {
QJSValue v;
ReadFunction(object, property, &v, notifier);
return QJSValuePrivate::get(v)->asV8Value(engine);
return v8::Value::fromVmValue(QJSValuePrivate::get(v)->getValue(QV8Engine::getV4(engine)));
} else if (property.isQVariant()) {
QVariant v;
ReadFunction(object, property, &v, notifier);
@ -2144,7 +2143,7 @@ void CallArgument::fromValue(int callType, QV8Engine *engine, v8::Handle<v8::Val
if (type != 0) { cleanup(); type = 0; }
if (callType == qMetaTypeId<QJSValue>()) {
qjsValuePtr = new (&allocData) QJSValue(QJSValuePrivate::get(new QJSValuePrivate(engine, value)));
qjsValuePtr = new (&allocData) QJSValue(new QJSValuePrivate(QV8Engine::getV4(engine), value.get()->vmValue()));
type = qMetaTypeId<QJSValue>();
} else if (callType == QMetaType::Int) {
intValue = quint32(value->Int32Value());
@ -2233,7 +2232,7 @@ void CallArgument::fromValue(int callType, QV8Engine *engine, v8::Handle<v8::Val
v8::Handle<v8::Value> CallArgument::toValue(QV8Engine *engine)
{
if (type == qMetaTypeId<QJSValue>()) {
return QJSValuePrivate::get(*qjsValuePtr)->asV8Value(engine);
return v8::Value::fromVmValue(QJSValuePrivate::get(*qjsValuePtr)->getValue(QV8Engine::getV4(engine)));
} else if (type == QMetaType::Int) {
return v8::Integer::New(int(intValue));
} else if (type == QMetaType::UInt) {

View File

@ -41,7 +41,7 @@
#include "qv8stringwrapper_p.h"
#include "qjsconverter_p.h"
#include "qjsconverter_impl_p.h"
#include "qjsconverter_p.h"
QT_BEGIN_NAMESPACE

View File

@ -46,7 +46,6 @@
#include <private/qqmlcontext_p.h>
#include <private/qjsvalue_p.h>
#include <private/qscript_impl_p.h>
QT_BEGIN_NAMESPACE
@ -196,10 +195,12 @@ v8::Handle<v8::Value> QV8TypeWrapper::Getter(v8::Local<v8::String> property,
v8::Handle<v8::Value> rv = v8engine->qobjectWrapper()->getProperty(qobjectSingleton, propertystring, context, QV8QObjectWrapper::IgnoreRevision);
return rv;
} else if (!siinfo->scriptApi(e).isUndefined()) {
QQmlJS::VM::ExecutionEngine *engine = v8::Isolate::GetEngine();
// 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);
QQmlJS::VM::Object *o = QJSValuePrivate::get(siinfo->scriptApi(e))->getValue(engine).asObject();
if (!o)
return v8::Handle<v8::Value>();
return v8::Value::fromVmValue(o->get(engine->current, property.get()->vmValue().toString(engine->current)));
}
// Fall through to return empty handle
@ -289,14 +290,14 @@ v8::Handle<v8::Value> QV8TypeWrapper::Setter(v8::Local<v8::String> property,
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) {
QQmlJS::VM::Value setVal = value.get()->vmValue();
QQmlJS::VM::Object *apiprivate = QJSValuePrivate::get(siinfo->scriptApi(e))->value.asObject();
if (!apiprivate) {
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());
apiprivate->put(v8::Isolate::GetEngine()->current, property.get()->vmValue().stringValue(), setVal);
}
}
}

View File

@ -13,9 +13,5 @@ HEADERS += \
$$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

View File

@ -55,6 +55,7 @@
#include <QtCore/qdebug.h>
#include <QtCore/qstack.h>
#include <QXmlStreamReader>
#include <QtCore/qdatetime.h>
QT_BEGIN_NAMESPACE

View File

@ -50,6 +50,7 @@
#include <qqmlinfo.h>
#include <private/qqmlengine_p.h>
#include <QtCore/QBuffer>
#include <QtCore/qdatetime.h>
QT_BEGIN_NAMESPACE

View File

@ -47,6 +47,7 @@
#include <QtQml/qqmlengine.h>
#include <QtNetwork/qnetworkreply.h>
#include <QtCore/qfile.h>
#include <QtCore/qmath.h>
#include <private/qqmlglobal_p.h>

View File

@ -53,6 +53,7 @@
#include <QtGui/qguiapplication.h>
#include <QtGui/private/qguiapplication_p.h>
#include <QtGui/qstylehints.h>
#include <QtCore/qmath.h>
#include "qplatformdefs.h"
QT_BEGIN_NAMESPACE

View File

@ -56,6 +56,7 @@
#include <QtGui/qstylehints.h>
#include <QtGui/qinputmethod.h>
#include <QtCore/qmath.h>
#ifndef QT_NO_ACCESSIBILITY
#include "qaccessible.h"

View File

@ -44,6 +44,7 @@
#include <QtCore/QWaitCondition>
#include <QtCore/QAnimationDriver>
#include <QtCore/QQueue>
#include <QtCore/QTime>
#include <QtGui/QGuiApplication>
#include <QtGui/QScreen>