Port the sequence (QList) wrapper away from v4classgen

This also gets rid of the QQmlSequenceBase base class.

Change-Id: I8cccc6c8924843ae37a4ee4ea95807f2b459d55b
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
This commit is contained in:
Simon Hausmann 2013-06-13 13:43:09 +02:00 committed by Lars Knoll
parent 50adb6318a
commit bc25d585de
4 changed files with 50 additions and 79 deletions

View File

@ -225,7 +225,7 @@ ExecutionEngine::ExecutionEngine(QQmlJS::EvalISelFactory *factory)
uRIErrorPrototype->init(this, uRIErrorCtor);
variantPrototype->initClass(this);
sequencePrototype->initClass(this);
sequencePrototype->init(this);
//
// set up the global object

View File

@ -159,12 +159,12 @@ template <> bool convertValueToElement(const QV4::Value &value)
}
template <typename Container>
class QQmlSequence : public QQmlSequenceBase
class QQmlSequence : public QV4::Object
{
Q_MANAGED
public:
QQmlSequence(QV4::ExecutionEngine *engine, const Container &container)
: QQmlSequenceBase(engine)
: QV4::Object(engine)
, m_container(container)
, m_object(0)
, m_propertyIndex(-1)
@ -173,11 +173,11 @@ public:
type = Type_QmlSequence;
vtbl = &static_vtbl;
prototype = engine->sequencePrototype;
initClass(engine);
init(engine);
}
QQmlSequence(QV4::ExecutionEngine *engine, QObject *object, int propertyIndex)
: QQmlSequenceBase(engine)
: QV4::Object(engine)
, m_object(object)
, m_propertyIndex(propertyIndex)
, m_isReference(true)
@ -186,7 +186,12 @@ public:
vtbl = &static_vtbl;
prototype = engine->sequencePrototype;
loadReference();
initClass(engine);
init(engine);
}
void init(ExecutionEngine *engine)
{
defineAccessorProperty(engine, QStringLiteral("length"), method_get_length, method_set_length);
}
QV4::Value containerGetIndexed(QV4::ExecutionContext *ctx, uint index, bool *hasProperty)
@ -278,7 +283,7 @@ public:
if (m_isReference) {
if (!m_object)
return QQmlSequenceBase::advanceIterator(this, it, name, index, attrs);
return QV4::Object::advanceIterator(this, it, name, index, attrs);
loadReference();
}
@ -290,7 +295,7 @@ public:
it->tmpDynamicProperty.value = convertElementToValue(engine(), m_container.at(*index));
return &it->tmpDynamicProperty;
}
return QQmlSequenceBase::advanceIterator(this, it, name, index, attrs);
return QV4::Object::advanceIterator(this, it, name, index, attrs);
}
bool containerDeleteIndexedProperty(QV4::ExecutionContext *ctx, uint index)
@ -382,56 +387,65 @@ public:
storeReference();
}
QV4::Value lengthGetter(QV4::SimpleCallContext*)
static QV4::Value method_get_length(QV4::SimpleCallContext *ctx)
{
if (m_isReference) {
if (!m_object)
QQmlSequence<Container> *This = ctx->thisObject.as<QQmlSequence<Container> >();
if (!This)
ctx->throwTypeError();
if (This->m_isReference) {
if (!This->m_object)
return QV4::Value::fromInt32(0);
loadReference();
This->loadReference();
}
return QV4::Value::fromInt32(m_container.count());
return QV4::Value::fromInt32(This->m_container.count());
}
void lengthSetter(QV4::SimpleCallContext* ctx)
static QV4::Value method_set_length(QV4::SimpleCallContext* ctx)
{
QQmlSequence<Container> *This = ctx->thisObject.as<QQmlSequence<Container> >();
if (!This)
ctx->throwTypeError();
quint32 newLength = ctx->arguments[0].toUInt32();
/* Qt containers have int (rather than uint) allowable indexes. */
if (newLength > INT_MAX) {
generateWarning(ctx, QLatin1String("Index out of range during length set"));
return;
return QV4::Value::undefinedValue();
}
/* Read the sequence from the QObject property if we're a reference */
if (m_isReference) {
if (!m_object)
return;
loadReference();
if (This->m_isReference) {
if (!This->m_object)
return QV4::Value::undefinedValue();
This->loadReference();
}
/* Determine whether we need to modify the sequence */
qint32 newCount = static_cast<qint32>(newLength);
qint32 count = m_container.count();
qint32 count = This->m_container.count();
if (newCount == count) {
return;
return QV4::Value::undefinedValue();
} else if (newCount > count) {
/* according to ECMA262r3 we need to insert */
/* undefined values increasing length to newLength. */
/* We cannot, so we insert default-values instead. */
m_container.reserve(newCount);
This->m_container.reserve(newCount);
while (newCount > count++) {
m_container.append(typename Container::value_type());
This->m_container.append(typename Container::value_type());
}
} else {
/* according to ECMA262r3 we need to remove */
/* elements until the sequence is the required length. */
while (newCount < count) {
count--;
m_container.removeAt(count);
This->m_container.removeAt(count);
}
}
/* write back if required. */
if (m_isReference) {
if (This->m_isReference) {
/* write back. already checked that object is non-null, so skip that check here. */
storeReference();
This->storeReference();
}
return QV4::Value::undefinedValue();
}
QVariant toVariant() const
@ -517,6 +531,12 @@ SequencePrototype::SequencePrototype(ExecutionEngine *engine)
}
#undef REGISTER_QML_SEQUENCE_METATYPE
void SequencePrototype::init(QV4::ExecutionEngine *engine)
{
defineDefaultProperty(engine, QStringLiteral("sort"), method_sort, 1);
defineDefaultProperty(engine, QStringLiteral("valueOf"), method_valueOf, 0);
}
QV4::Value SequencePrototype::method_sort(QV4::SimpleCallContext *ctx)
{
QV4::Object *o = ctx->thisObject.asObject();
@ -537,38 +557,6 @@ QV4::Value SequencePrototype::method_sort(QV4::SimpleCallContext *ctx)
return ctx->thisObject;
}
QV4::Value QQmlSequenceBase::method_get_length(QV4::SimpleCallContext* ctx) QV4_ANNOTATE(attributes QV4::Attr_ReadOnly)
{
QV4::Object *o = ctx->thisObject.asObject();
if (!o)
ctx->throwTypeError();
#define CALL_LENGTH_GETTER(SequenceElementType, SequenceElementTypeName, SequenceType, DefaultValue) \
if (QQml##SequenceElementTypeName##List *s = o->as<QQml##SequenceElementTypeName##List>()) { \
return s->lengthGetter(ctx); \
} else
FOREACH_QML_SEQUENCE_TYPE(CALL_LENGTH_GETTER)
#undef CALL_LENGTH_GETTER
return QV4::Value::undefinedValue();
}
QV4::Value QQmlSequenceBase::method_set_length(QV4::SimpleCallContext* ctx)
{
QV4::Object *o = ctx->thisObject.asObject();
if (!o)
ctx->throwTypeError();
#define CALL_LENGTH_SETTER(SequenceElementType, SequenceElementTypeName, SequenceType, DefaultValue) \
if (QQml##SequenceElementTypeName##List *s = o->as<QQml##SequenceElementTypeName##List>()) { \
s->lengthSetter(ctx); \
} else
FOREACH_QML_SEQUENCE_TYPE(CALL_LENGTH_SETTER)
#undef CALL_LENGTH_SETTER
return QV4::Value::undefinedValue();
}
#define IS_SEQUENCE(unused1, unused2, SequenceType, unused3) \
if (sequenceTypeId == qMetaTypeId<SequenceType>()) { \
return true; \
@ -660,6 +648,4 @@ int SequencePrototype::metaTypeForSequence(QV4::Object *object)
#undef MAP_META_TYPE
#include "qv4sequenceobject_p_jsclass.cpp"
QT_END_NAMESPACE

View File

@ -63,32 +63,18 @@ QT_BEGIN_NAMESPACE
namespace QV4 {
class QV4_JS_CLASS(QQmlSequenceBase) : public QV4::Object
{
public:
QQmlSequenceBase(QV4::ExecutionEngine *engine)
: QV4::Object(engine)
{}
void initClass(QV4::ExecutionEngine *engine);
static QV4::Value method_get_length(QV4::SimpleCallContext* ctx) QV4_ANNOTATE(attributes QV4::Attr_ReadOnly);
static QV4::Value method_set_length(QV4::SimpleCallContext* ctx);
};
struct QV4_JS_CLASS(SequencePrototype) : public QV4::Object
struct SequencePrototype : public QV4::Object
{
SequencePrototype(QV4::ExecutionEngine *engine);
void initClass(QV4::ExecutionEngine *engine);
void init(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 QV4::Value method_sort(QV4::SimpleCallContext *ctx);
static bool isSequenceType(int sequenceTypeId);
static QV4::Value newSequence(QV4::ExecutionEngine *engine, int sequenceTypeId, QObject *object, int propertyIndex, bool *succeeded);

View File

@ -111,8 +111,7 @@ OTHER_FILES += \
$$PWD/v4classgen
JS_CLASS_SOURCES += $$PWD/qv4dateobject_p.h \
$$PWD/qv4variantobject_p.h \
$$PWD/qv4sequenceobject_p.h
$$PWD/qv4variantobject_p.h
js_class_bindings.output = ${QMAKE_FILE_BASE}_jsclass.cpp
js_class_bindings.input = JS_CLASS_SOURCES