Finalize sequence wrapping

* Move into QV4 namespace
* Get rid of sequence wrapper instance, all static methods now

Change-Id: I9a9e7ce10890cfe4625b3571bdb4b0ffec34658a
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
This commit is contained in:
Simon Hausmann 2013-05-21 17:06:36 +02:00 committed by Lars Knoll
parent 2ae06077a2
commit 9de9a3eca4
10 changed files with 83 additions and 115 deletions

View File

@ -62,6 +62,7 @@
#include <qv4unwindhelper_p.h>
#include "qv4debugging_p.h"
#include "qv4executableallocator_p.h"
#include "qv4sequenceobject_p.h"
#ifdef V4_ENABLE_JIT
# include "qv4isel_masm_p.h"
@ -145,6 +146,7 @@ ExecutionEngine::ExecutionEngine(QQmlJS::EvalISelFactory *factory)
uRIErrorPrototype = new (memoryManager) URIErrorPrototype(this);
variantPrototype = new (memoryManager) VariantPrototype(this);
sequencePrototype = new (memoryManager) SequencePrototype(this);
stringPrototype->prototype = objectPrototype;
numberPrototype->prototype = objectPrototype;
@ -210,6 +212,7 @@ ExecutionEngine::ExecutionEngine(QQmlJS::EvalISelFactory *factory)
uRIErrorPrototype->init(this, uRIErrorCtor);
variantPrototype->initClass(this);
sequencePrototype->initClass(this);
//
// set up the global object
@ -628,6 +631,7 @@ void ExecutionEngine::markObjects()
uRIErrorPrototype->mark();
variantPrototype->mark();
sequencePrototype->mark();
}
Value ExecutionEngine::run(Function *function, ExecutionContext *ctx)

View File

@ -99,6 +99,7 @@ struct SyntaxErrorPrototype;
struct TypeErrorPrototype;
struct URIErrorPrototype;
struct VariantPrototype;
struct SequencePrototype;
struct EvalFunction;
struct Identifiers;
struct InternalClass;
@ -163,6 +164,7 @@ struct Q_QML_EXPORT ExecutionEngine
URIErrorPrototype *uRIErrorPrototype;
VariantPrototype *variantPrototype;
SequencePrototype *sequencePrototype;
QQmlJS::MemoryPool classPool;
InternalClass *emptyClass;

View File

@ -41,8 +41,7 @@
#include <QtQml/qqml.h>
#include "qv8sequencewrapper_p.h"
#include "qv8engine_p.h"
#include "qv4sequenceobject_p.h"
#include <private/qv4functionobject_p.h>
#include <private/qv4arrayobject_p.h>
@ -50,6 +49,8 @@
QT_BEGIN_NAMESPACE
using namespace QV4;
// helper function to generate valid warnings if errors occur during sequence operations.
static void generateWarning(QV4::ExecutionContext *ctx, const QString& description)
{
@ -72,34 +73,6 @@ static void generateWarning(QV4::ExecutionContext *ctx, const QString& descripti
F(QString, QString, QStringList, QString()) \
F(QUrl, Url, QList<QUrl>, QUrl())
class QV4_JS_CLASS(QQmlSequenceBase) : public QV4::Object
{
public:
QQmlSequenceBase(QV4::ExecutionEngine *engine)
: QV4::Object(engine)
{}
void initClass(QV4::ExecutionEngine *engine);
QV4::Value method_get_length(QV4::SimpleCallContext* ctx) QV4_ANNOTATE(attributes QV4::Attr_ReadOnly);
QV4::Value method_set_length(QV4::SimpleCallContext* ctx);
};
class QV4_JS_CLASS(QQmlSequencePrototype) : public QV4::Object
{
QV4_ANNOTATE(staticInitClass true)
public:
static void initClass(QV4::ExecutionEngine *engine, const QV4::Value &value);
static QV4::Value method_valueOf(QV4::SimpleCallContext *ctx)
{
return QV4::Value::fromString(ctx->thisObject.toString(ctx));
}
static QV4::Value method_sort(QV4::SimpleCallContext *ctx) QV4_ARGC(1);
};
static QV4::Value convertElementToValue(QV4::ExecutionContext *ctx, const QString &element)
{
return QV4::Value::fromString(ctx, element);
@ -195,7 +168,7 @@ public:
{
type = ManagedType;
vtbl = &static_vtbl;
prototype = engine->arrayPrototype;
prototype = engine->sequencePrototype;
initClass(engine);
}
@ -207,7 +180,7 @@ public:
{
type = ManagedType;
vtbl = &static_vtbl;
prototype = engine->arrayPrototype;
prototype = engine->sequencePrototype;
loadReference();
initClass(engine);
}
@ -494,7 +467,16 @@ typedef QQmlSequence<QList<qreal>, QV4::Managed::Type_QmlRealList> QQmlRealList;
template<>
DEFINE_MANAGED_VTABLE(QQmlRealList);
QV4::Value QQmlSequencePrototype::method_sort(QV4::SimpleCallContext *ctx)
#define REGISTER_QML_SEQUENCE_METATYPE(unused, unused2, SequenceType, unused3) qRegisterMetaType<SequenceType>();
SequencePrototype::SequencePrototype(ExecutionEngine *engine)
: QV4::Object(engine)
{
prototype = engine->arrayPrototype;
FOREACH_QML_SEQUENCE_TYPE(REGISTER_QML_SEQUENCE_METATYPE)
}
#undef REGISTER_QML_SEQUENCE_METATYPE
QV4::Value SequencePrototype::method_sort(QV4::SimpleCallContext *ctx)
{
QV4::Object *o = ctx->thisObject.asObject();
if (!o || !o->isListType())
@ -541,38 +523,12 @@ QV4::Value QQmlSequenceBase::method_set_length(QV4::SimpleCallContext* ctx)
return QV4::Value::undefinedValue();
}
QV8SequenceWrapper::QV8SequenceWrapper()
: m_engine(0)
{
}
QV8SequenceWrapper::~QV8SequenceWrapper()
{
}
#define REGISTER_QML_SEQUENCE_METATYPE(unused, unused2, SequenceType, unused3) qRegisterMetaType<SequenceType>();
void QV8SequenceWrapper::init(QV8Engine *engine)
{
FOREACH_QML_SEQUENCE_TYPE(REGISTER_QML_SEQUENCE_METATYPE)
m_engine = QV8Engine::getV4(engine);
m_prototype = QV4::Value::fromObject(m_engine->newObject());
m_prototype.value().asObject()->prototype = m_engine->arrayPrototype;
QQmlSequencePrototype::initClass(m_engine, m_prototype.value());
}
#undef REGISTER_QML_SEQUENCE_METATYPE
void QV8SequenceWrapper::destroy()
{
}
#define IS_SEQUENCE(unused1, unused2, SequenceType, unused3) \
if (sequenceTypeId == qMetaTypeId<SequenceType>()) { \
return true; \
} else
bool QV8SequenceWrapper::isSequenceType(int sequenceTypeId) const
bool SequencePrototype::isSequenceType(int sequenceTypeId)
{
FOREACH_QML_SEQUENCE_TYPE(IS_SEQUENCE) { /* else */ return false; }
}
@ -580,12 +536,11 @@ bool QV8SequenceWrapper::isSequenceType(int sequenceTypeId) const
#define NEW_REFERENCE_SEQUENCE(ElementType, ElementTypeName, SequenceType, unused) \
if (sequenceType == qMetaTypeId<SequenceType>()) { \
QV4::Object *obj = new (m_engine->memoryManager) QQml##ElementTypeName##List(m_engine, object, propertyIndex); \
obj->prototype = m_prototype.value().asObject(); \
QV4::Object *obj = new (engine->memoryManager) QQml##ElementTypeName##List(engine, object, propertyIndex); \
return QV4::Value::fromObject(obj); \
} else
QV4::Value QV8SequenceWrapper::newSequence(int sequenceType, QObject *object, int propertyIndex, bool *succeeded)
QV4::Value SequencePrototype::newSequence(QV4::ExecutionEngine *engine, int sequenceType, QObject *object, int propertyIndex, bool *succeeded)
{
// This function is called when the property is a QObject Q_PROPERTY of
// the given sequence type. Internally we store a typed-sequence
@ -598,12 +553,11 @@ QV4::Value QV8SequenceWrapper::newSequence(int sequenceType, QObject *object, in
#define NEW_COPY_SEQUENCE(ElementType, ElementTypeName, SequenceType, unused) \
if (sequenceType == qMetaTypeId<SequenceType>()) { \
QV4::Object *obj = new (m_engine->memoryManager) QQml##ElementTypeName##List(m_engine, v.value<SequenceType >()); \
obj->prototype = m_prototype.value().asObject(); \
QV4::Object *obj = new (engine->memoryManager) QQml##ElementTypeName##List(engine, v.value<SequenceType >()); \
return QV4::Value::fromObject(obj); \
} else
QV4::Value QV8SequenceWrapper::fromVariant(const QVariant& v, bool *succeeded)
QV4::Value SequencePrototype::fromVariant(QV4::ExecutionEngine *engine, const QVariant& v, bool *succeeded)
{
// This function is called when assigning a sequence value to a normal JS var
// in a JS block. Internally, we store a sequence of the specified type.
@ -620,7 +574,7 @@ QV4::Value QV8SequenceWrapper::fromVariant(const QVariant& v, bool *succeeded)
return list->toVariant(); \
else
QVariant QV8SequenceWrapper::toVariant(QV4::Object *object)
QVariant SequencePrototype::toVariant(QV4::Object *object)
{
Q_ASSERT(object->isListType());
FOREACH_QML_SEQUENCE_TYPE(SEQUENCE_TO_VARIANT) { /* else */ return QVariant(); }
@ -631,7 +585,7 @@ QVariant QV8SequenceWrapper::toVariant(QV4::Object *object)
return QQml##ElementTypeName##List::toVariant(a); \
} else
QVariant QV8SequenceWrapper::toVariant(const QV4::Value &array, int typeHint, bool *succeeded)
QVariant SequencePrototype::toVariant(const QV4::Value &array, int typeHint, bool *succeeded)
{
*succeeded = true;
@ -648,7 +602,7 @@ QVariant QV8SequenceWrapper::toVariant(const QV4::Value &array, int typeHint, bo
#define MAP_META_TYPE(ElementType, ElementTypeName, SequenceType, unused) \
case QV4::Managed::Type_Qml##ElementTypeName##List: return qMetaTypeId<SequenceType>();
int QV8SequenceWrapper::metaTypeForSequence(QV4::Object *object)
int SequencePrototype::metaTypeForSequence(QV4::Object *object)
{
switch (object->internalType()) {
FOREACH_QML_SEQUENCE_TYPE(MAP_META_TYPE)
@ -659,6 +613,6 @@ int QV8SequenceWrapper::metaTypeForSequence(QV4::Object *object)
#undef MAP_META_TYPE
#include "qv8sequencewrapper_jsclass.cpp"
#include "qv4sequenceobject_p_jsclass.cpp"
QT_END_NAMESPACE

View File

@ -39,8 +39,8 @@
**
****************************************************************************/
#ifndef QV8SEQUENCEWRAPPER_P_H
#define QV8SEQUENCEWRAPPER_P_H
#ifndef QV4SEQUENCEWRAPPER_P_H
#define QV4SEQUENCEWRAPPER_P_H
//
// W A R N I N G
@ -56,37 +56,51 @@
#include <QtCore/qglobal.h>
#include <QtCore/qvariant.h>
#include <private/qv4value_p.h>
#include "qv4value_p.h"
#include "qv4object_p.h"
QT_BEGIN_NAMESPACE
class QV8Engine;
class QV8ObjectResource;
namespace QV4 {
class QV8SequenceWrapper
class QV4_JS_CLASS(QQmlSequenceBase) : public QV4::Object
{
public:
QV8SequenceWrapper();
~QV8SequenceWrapper();
QQmlSequenceBase(QV4::ExecutionEngine *engine)
: QV4::Object(engine)
{}
void init(QV8Engine *);
void destroy();
void initClass(QV4::ExecutionEngine *engine);
bool isSequenceType(int sequenceTypeId) const;
QV4::Value method_get_length(QV4::SimpleCallContext* ctx) QV4_ANNOTATE(attributes QV4::Attr_ReadOnly);
QV4::Value newSequence(int sequenceTypeId, QObject *object, int propertyIndex, bool *succeeded);
QV4::Value fromVariant(const QVariant& v, bool *succeeded);
QVariant toVariant(QV4::Object *object);
QVariant toVariant(const QV4::Value &array, int typeHint, bool *succeeded);
int metaTypeForSequence(QV4::Object *object);
private:
QV4::ExecutionEngine *m_engine;
QV4::PersistentValue m_prototype;
QV4::Value method_set_length(QV4::SimpleCallContext* ctx);
};
class QV4_JS_CLASS(SequencePrototype) : public QV4::Object
{
public:
SequencePrototype(QV4::ExecutionEngine *engine);
void initClass(QV4::ExecutionEngine *engine);
static QV4::Value method_valueOf(QV4::SimpleCallContext *ctx)
{
return QV4::Value::fromString(ctx->thisObject.toString(ctx));
}
static QV4::Value method_sort(QV4::SimpleCallContext *ctx) QV4_ARGC(1);
static bool isSequenceType(int sequenceTypeId);
static QV4::Value newSequence(QV4::ExecutionEngine *engine, int sequenceTypeId, QObject *object, int propertyIndex, bool *succeeded);
static QV4::Value fromVariant(QV4::ExecutionEngine *engine, const QVariant& v, bool *succeeded);
static int metaTypeForSequence(QV4::Object *object);
static QVariant toVariant(QV4::Object *object);
static QVariant toVariant(const QV4::Value &array, int typeHint, bool *succeeded);
};
}
QT_END_NAMESPACE
#endif // QV8SEQUENCEWRAPPER_P_H
#endif // QV4SEQUENCEWRAPPER_P_H

View File

@ -246,7 +246,7 @@ void Serialize::serialize(QByteArray &data, const QV4::Value &v, QV8Engine *engi
}
reserve(data, sizeof(quint32) + length * sizeof(quint32));
push(data, valueheader(WorkerSequence, length));
serialize(data, QV4::Value::fromInt32(engine->sequenceWrapper()->metaTypeForSequence(o)), engine); // sequence type
serialize(data, QV4::Value::fromInt32(QV4::SequencePrototype::metaTypeForSequence(o)), engine); // sequence type
for (uint32_t ii = 0; ii < seqLength; ++ii)
serialize(data, o->getIndexed(ii), engine); // sequence elements
@ -380,8 +380,8 @@ QV4::Value Serialize::deserialize(const char *&data, QV8Engine *engine)
array->arrayData[ii].value = deserialize(data, engine);
array->arrayDataLen = seqLength;
array->setArrayLengthUnchecked(seqLength);
QVariant seqVariant = engine->sequenceWrapper()->toVariant(QV4::Value::fromObject(array), sequenceType, &succeeded);
return engine->sequenceWrapper()->fromVariant(seqVariant, &succeeded);
QVariant seqVariant = QV4::SequencePrototype::toVariant(QV4::Value::fromObject(array), sequenceType, &succeeded);
return QV4::SequencePrototype::fromVariant(v4, seqVariant, &succeeded);
}
}
Q_ASSERT(!"Unreachable");

View File

@ -49,7 +49,8 @@ SOURCES += \
$$PWD/qv4unwindhelper.cpp \
$$PWD/qv4serialize.cpp \
$$PWD/qv4v8.cpp \
$$PWD/qv4executableallocator.cpp
$$PWD/qv4executableallocator.cpp \
$$PWD/qv4sequenceobject.cpp
HEADERS += \
$$PWD/qv4global_p.h \
@ -98,13 +99,15 @@ HEADERS += \
$$PWD/qv4v8_p.h \
$$PWD/qcalculatehash_p.h \
$$PWD/qv4util_p.h \
$$PWD/qv4executableallocator_p.h
$$PWD/qv4executableallocator_p.h \
$$PWD/qv4sequenceobject_p.h
JS_CLASS_SOURCES += $$PWD/qv4dateobject_p.h \
$$PWD/qv4stringobject_p.h \
$$PWD/qv4booleanobject_p.h \
$$PWD/qv4regexpobject_p.h \
$$PWD/qv4variantobject_p.h
$$PWD/qv4variantobject_p.h \
$$PWD/qv4sequenceobject_p.h
js_class_bindings.output = ${QMAKE_FILE_BASE}_jsclass.cpp
js_class_bindings.input = JS_CLASS_SOURCES

View File

@ -43,7 +43,7 @@
#include "qv8contextwrapper_p.h"
#include "qv8valuetypewrapper_p.h"
#include "qv8sequencewrapper_p.h"
#include "qv4sequenceobject_p.h"
#include "qv8include_p.h"
#include "qjsengine_p.h"
@ -157,7 +157,6 @@ QV8Engine::QV8Engine(QJSEngine* qq)
m_typeWrapper.init(this);
m_listWrapper.init(this);
m_valueTypeWrapper.init(this);
m_sequenceWrapper.init(this);
m_jsonWrapper.init(m_v4Engine);
}
@ -174,7 +173,6 @@ QV8Engine::~QV8Engine()
m_listModelData = 0;
m_jsonWrapper.destroy();
m_sequenceWrapper.destroy();
m_valueTypeWrapper.destroy();
m_listWrapper.destroy();
m_typeWrapper.destroy();
@ -232,7 +230,7 @@ QVariant QV8Engine::toVariant(const QV4::Value &value, int typeHint)
&& !value.asArrayObject() && !value.asFunctionObject()) {
return QVariant::fromValue(jsonObjectFromJS(value));
} else if (object->isListType())
return m_sequenceWrapper.toVariant(object);
return QV4::SequencePrototype::toVariant(object);
}
if (QV4::ArrayObject *a = value.asArrayObject()) {
@ -254,7 +252,7 @@ QVariant QV8Engine::toVariant(const QV4::Value &value, int typeHint)
}
bool succeeded = false;
QVariant retn = m_sequenceWrapper.toVariant(value, typeHint, &succeeded);
QVariant retn = QV4::SequencePrototype::toVariant(value, typeHint, &succeeded);
if (succeeded)
return retn;
}
@ -348,7 +346,7 @@ QV4::Value QV8Engine::fromVariant(const QVariant &variant)
case QMetaType::QStringList:
{
bool succeeded = false;
v8::Handle<v8::Value> retn = m_sequenceWrapper.fromVariant(variant, &succeeded);
v8::Handle<v8::Value> retn = QV4::SequencePrototype::fromVariant(m_v4Engine, variant, &succeeded);
if (succeeded)
return retn->v4Value();
return arrayFromStringList(this, *reinterpret_cast<const QStringList *>(ptr));
@ -400,7 +398,7 @@ QV4::Value QV8Engine::fromVariant(const QVariant &variant)
return newQObject(obj);
bool succeeded = false;
v8::Handle<v8::Value> retn = m_sequenceWrapper.fromVariant(variant, &succeeded);
v8::Handle<v8::Value> retn = QV4::SequencePrototype::fromVariant(m_v4Engine, variant, &succeeded);
if (succeeded)
return retn->v4Value();

View File

@ -76,7 +76,7 @@
#include "qv8typewrapper_p.h"
#include "qv8listwrapper_p.h"
#include "qv8valuetypewrapper_p.h"
#include "qv8sequencewrapper_p.h"
#include <private/qv4sequenceobject_p.h>
#include "qv4jsonwrapper_p.h"
#include <private/qv4value_p.h>
#include <private/qv4object_p.h>
@ -278,7 +278,6 @@ public:
QV8TypeWrapper *typeWrapper() { return &m_typeWrapper; }
QV8ListWrapper *listWrapper() { return &m_listWrapper; }
QV8ValueTypeWrapper *valueTypeWrapper() { return &m_valueTypeWrapper; }
QV8SequenceWrapper *sequenceWrapper() { return &m_sequenceWrapper; }
void *xmlHttpRequestData() { return m_xmlHttpRequestData; }
@ -426,7 +425,6 @@ protected:
QV8TypeWrapper m_typeWrapper;
QV8ListWrapper m_listWrapper;
QV8ValueTypeWrapper m_valueTypeWrapper;
QV8SequenceWrapper m_sequenceWrapper;
QV4JsonWrapper m_jsonWrapper;
QV4::PersistentValue m_freezeObject;
@ -516,7 +514,7 @@ QVariant QV8Engine::toValueType(const QV4::Value &obj)
QV4::Value QV8Engine::newSequence(int sequenceType, QObject *object, int property, bool *succeeded)
{
return m_sequenceWrapper.newSequence(sequenceType, object, property, succeeded);
return QV4::SequencePrototype::newSequence(m_v4Engine, sequenceType, object, property, succeeded);
}
QV4::Value QV8Engine::bindingFlagKey() const

View File

@ -2199,7 +2199,7 @@ void CallArgument::fromValue(int callType, QV8Engine *engine, v8::Handle<v8::Val
} else if (v.canConvert(callType)) {
*qvariantPtr = v;
qvariantPtr->convert(callType);
} else if (engine->sequenceWrapper()->isSequenceType(callType) && v.userType() == qMetaTypeId<QVariantList>()) {
} else if (QV4::SequencePrototype::isSequenceType(callType) && v.userType() == qMetaTypeId<QVariantList>()) {
// convert the JS array to a sequence of the correct type.
QVariant seqV = engine->toVariant(value->v4Value(), callType);
*qvariantPtr = seqV;

View File

@ -5,7 +5,6 @@ HEADERS += \
$$PWD/qv8debug_p.h \
$$PWD/qv8profiler_p.h \
$$PWD/qv8engine_p.h \
$$PWD/qv8sequencewrapper_p.h \
$$PWD/qv8contextwrapper_p.h \
$$PWD/qv8qobjectwrapper_p.h \
$$PWD/qv8typewrapper_p.h \
@ -21,7 +20,6 @@ HEADERS += \
SOURCES += \
$$PWD/qv8engine.cpp \
$$PWD/qv8sequencewrapper.cpp \
$$PWD/qv8contextwrapper.cpp \
$$PWD/qv8qobjectwrapper.cpp \
$$PWD/qv8typewrapper.cpp \
@ -34,6 +32,3 @@ SOURCES += \
$$PWD/qv4sqlerrors.cpp \
$$PWD/qqmlbuiltinfunctions.cpp
JS_CLASS_SOURCES += \
$$PWD/qv8sequencewrapper.cpp