diff options
Diffstat (limited to 'src/qml/jsruntime/qv4sequenceobject.cpp')
-rw-r--r-- | src/qml/jsruntime/qv4sequenceobject.cpp | 219 |
1 files changed, 106 insertions, 113 deletions
diff --git a/src/qml/jsruntime/qv4sequenceobject.cpp b/src/qml/jsruntime/qv4sequenceobject.cpp index 89231cfe5f..b55cd2daad 100644 --- a/src/qml/jsruntime/qv4sequenceobject.cpp +++ b/src/qml/jsruntime/qv4sequenceobject.cpp @@ -58,13 +58,13 @@ using namespace QV4; // helper function to generate valid warnings if errors occur during sequence operations. static void generateWarning(QV4::ExecutionContext *ctx, const QString& description) { - QQmlEngine *engine = ctx->engine->v8Engine->engine(); + QQmlEngine *engine = ctx->d()->engine->v8Engine->engine(); if (!engine) return; QQmlError retn; retn.setDescription(description); - QV4::StackFrame frame = ctx->engine->currentStackFrame(); + QV4::StackFrame frame = ctx->d()->engine->currentStackFrame(); retn.setLine(frame.line); retn.setUrl(QUrl(frame.source)); @@ -163,38 +163,41 @@ template <> bool convertValueToElement(const ValueRef value) } template <typename Container> -class QQmlSequence : public QV4::Object +struct QQmlSequence : public QV4::Object { - V4_OBJECT + struct Data : Object::Data { + Data(QV4::ExecutionEngine *engine, const Container &container) + : Object::Data(InternalClass::create(engine, staticVTable(), engine->sequencePrototype.asObject())) + , container(container) + , propertyIndex(-1) + , isReference(false) + { + QV4::Scope scope(engine); + QV4::Scoped<QQmlSequence<Container> > o(scope, this); + o->setArrayType(ArrayData::Custom); + o->init(); + } + + Data(QV4::ExecutionEngine *engine, QObject *object, int propertyIndex) + : Object::Data(InternalClass::create(engine, staticVTable(), engine->sequencePrototype.asObject())) + , object(object) + , propertyIndex(propertyIndex) + , isReference(true) + { + QV4::Scope scope(engine); + QV4::Scoped<QQmlSequence<Container> > o(scope, this); + o->setArrayType(ArrayData::Custom); + o->loadReference(); + o->init(); + } + mutable Container container; + QPointer<QObject> object; + int propertyIndex; + bool isReference; + }; + V4_OBJECT(QV4::Object) Q_MANAGED_TYPE(QmlSequence) public: - QQmlSequence(QV4::ExecutionEngine *engine, const Container &container) - : QV4::Object(InternalClass::create(engine, staticVTable(), engine->sequencePrototype.asObject())) - , m_container(container) - , m_object(0) - , m_propertyIndex(-1) - , m_isReference(false) - { - QV4::Scope scope(engine); - QV4::ScopedObject protectThis(scope, this); - Q_UNUSED(protectThis); - setArrayType(ArrayData::Custom); - init(); - } - - QQmlSequence(QV4::ExecutionEngine *engine, QObject *object, int propertyIndex) - : QV4::Object(InternalClass::create(engine, staticVTable(), engine->sequencePrototype.asObject())) - , m_object(object) - , m_propertyIndex(propertyIndex) - , m_isReference(true) - { - QV4::Scope scope(engine); - QV4::ScopedObject protectThis(scope, this); - Q_UNUSED(protectThis); - setArrayType(ArrayData::Custom); - loadReference(); - init(); - } void init() { @@ -210,8 +213,8 @@ public: *hasProperty = false; return Encode::undefined(); } - if (m_isReference) { - if (!m_object) { + if (d()->isReference) { + if (!d()->object) { if (hasProperty) *hasProperty = false; return Encode::undefined(); @@ -219,10 +222,10 @@ public: loadReference(); } qint32 signedIdx = static_cast<qint32>(index); - if (signedIdx < m_container.count()) { + if (signedIdx < d()->container.count()) { if (hasProperty) *hasProperty = true; - return convertElementToValue(engine(), m_container.at(signedIdx)); + return convertElementToValue(engine(), d()->container.at(signedIdx)); } if (hasProperty) *hasProperty = false; @@ -231,7 +234,7 @@ public: void containerPutIndexed(uint index, const QV4::ValueRef value) { - if (internalClass->engine->hasException) + if (internalClass()->engine->hasException) return; /* Qt containers have int (rather than uint) allowable indexes. */ @@ -240,33 +243,33 @@ public: return; } - if (m_isReference) { - if (!m_object) + if (d()->isReference) { + if (!d()->object) return; loadReference(); } qint32 signedIdx = static_cast<qint32>(index); - int count = m_container.count(); + int count = d()->container.count(); typename Container::value_type element = convertValueToElement<typename Container::value_type>(value); if (signedIdx == count) { - m_container.append(element); + d()->container.append(element); } else if (signedIdx < count) { - m_container[signedIdx] = element; + d()->container[signedIdx] = element; } else { /* according to ECMA262r3 we need to insert */ /* the value at the given index, increasing length to index+1. */ - m_container.reserve(signedIdx + 1); + d()->container.reserve(signedIdx + 1); while (signedIdx > count++) { - m_container.append(typename Container::value_type()); + d()->container.append(typename Container::value_type()); } - m_container.append(element); + d()->container.append(element); } - if (m_isReference) + if (d()->isReference) storeReference(); } @@ -277,33 +280,33 @@ public: generateWarning(engine()->currentContext(), QLatin1String("Index out of range during indexed query")); return QV4::Attr_Invalid; } - if (m_isReference) { - if (!m_object) + if (d()->isReference) { + if (!d()->object) return QV4::Attr_Invalid; loadReference(); } qint32 signedIdx = static_cast<qint32>(index); - return (signedIdx < m_container.count()) ? QV4::Attr_Data : QV4::Attr_Invalid; + return (signedIdx < d()->container.count()) ? QV4::Attr_Data : QV4::Attr_Invalid; } - void containerAdvanceIterator(ObjectIterator *it, StringRef name, uint *index, Property *p, PropertyAttributes *attrs) + void containerAdvanceIterator(ObjectIterator *it, String *&name, uint *index, Property *p, PropertyAttributes *attrs) { name = (String *)0; *index = UINT_MAX; - if (m_isReference) { - if (!m_object) { + if (d()->isReference) { + if (!d()->object) { QV4::Object::advanceIterator(this, it, name, index, p, attrs); return; } loadReference(); } - if (it->arrayIndex < static_cast<uint>(m_container.count())) { + if (it->arrayIndex < static_cast<uint>(d()->container.count())) { *index = it->arrayIndex; ++it->arrayIndex; *attrs = QV4::Attr_Data; - p->value = convertElementToValue(engine(), m_container.at(*index)); + p->value = convertElementToValue(engine(), d()->container.at(*index)); return; } QV4::Object::advanceIterator(this, it, name, index, p, attrs); @@ -314,21 +317,21 @@ public: /* Qt containers have int (rather than uint) allowable indexes. */ if (index > INT_MAX) return false; - if (m_isReference) { - if (!m_object) + if (d()->isReference) { + if (!d()->object) return false; loadReference(); } qint32 signedIdx = static_cast<qint32>(index); - if (signedIdx >= m_container.count()) + if (signedIdx >= d()->container.count()) return false; /* according to ECMA262r3 it should be Undefined, */ /* but we cannot, so we insert a default-value instead. */ - m_container.replace(signedIdx, typename Container::value_type()); + d()->container.replace(signedIdx, typename Container::value_type()); - if (m_isReference) + if (d()->isReference) storeReference(); return true; @@ -339,9 +342,9 @@ public: QQmlSequence<Container> *otherSequence = other->as<QQmlSequence<Container> >(); if (!otherSequence) return false; - if (m_isReference && otherSequence->m_isReference) { - return m_object == otherSequence->m_object && m_propertyIndex == otherSequence->m_propertyIndex; - } else if (!m_isReference && !otherSequence->m_isReference) { + if (d()->isReference && otherSequence->d()->isReference) { + return d()->object == otherSequence->d()->object && d()->propertyIndex == otherSequence->d()->propertyIndex; + } else if (!d()->isReference && !otherSequence->d()->isReference) { return this == otherSequence; } return false; @@ -366,9 +369,9 @@ public: QV4::Scope scope(m_ctx); ScopedObject compare(scope, m_compareFn); ScopedCallData callData(scope, 2); - callData->args[0] = convertElementToValue(this->m_ctx->engine, lhs); - callData->args[1] = convertElementToValue(this->m_ctx->engine, rhs); - callData->thisObject = this->m_ctx->engine->globalObject; + callData->args[0] = convertElementToValue(this->m_ctx->d()->engine, lhs); + callData->args[1] = convertElementToValue(this->m_ctx->d()->engine, rhs); + callData->thisObject = this->m_ctx->d()->engine->globalObject; QV4::ScopedValue result(scope, compare->call(callData)); return result->toNumber() < 0; } @@ -380,82 +383,82 @@ public: void sort(QV4::CallContext *ctx) { - if (m_isReference) { - if (!m_object) + if (d()->isReference) { + if (!d()->object) return; loadReference(); } QV4::Scope scope(ctx); - if (ctx->callData->argc == 1 && ctx->callData->args[0].asFunctionObject()) { - CompareFunctor cf(ctx, ctx->callData->args[0]); - std::sort(m_container.begin(), m_container.end(), cf); + if (ctx->d()->callData->argc == 1 && ctx->d()->callData->args[0].asFunctionObject()) { + CompareFunctor cf(ctx, ctx->d()->callData->args[0]); + std::sort(d()->container.begin(), d()->container.end(), cf); } else { DefaultCompareFunctor cf; - std::sort(m_container.begin(), m_container.end(), cf); + std::sort(d()->container.begin(), d()->container.end(), cf); } - if (m_isReference) + if (d()->isReference) storeReference(); } static QV4::ReturnedValue method_get_length(QV4::CallContext *ctx) { QV4::Scope scope(ctx); - QV4::Scoped<QQmlSequence<Container> > This(scope, ctx->callData->thisObject.as<QQmlSequence<Container> >()); + QV4::Scoped<QQmlSequence<Container> > This(scope, ctx->d()->callData->thisObject.as<QQmlSequence<Container> >()); if (!This) return ctx->throwTypeError(); - if (This->m_isReference) { - if (!This->m_object) + if (This->d()->isReference) { + if (!This->d()->object) return QV4::Encode(0); This->loadReference(); } - return QV4::Encode(This->m_container.count()); + return QV4::Encode(This->d()->container.count()); } static QV4::ReturnedValue method_set_length(QV4::CallContext* ctx) { QV4::Scope scope(ctx); - QV4::Scoped<QQmlSequence<Container> > This(scope, ctx->callData->thisObject.as<QQmlSequence<Container> >()); + QV4::Scoped<QQmlSequence<Container> > This(scope, ctx->d()->callData->thisObject.as<QQmlSequence<Container> >()); if (!This) return ctx->throwTypeError(); - quint32 newLength = ctx->callData->args[0].toUInt32(); + quint32 newLength = ctx->d()->callData->args[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 QV4::Encode::undefined(); } /* Read the sequence from the QObject property if we're a reference */ - if (This->m_isReference) { - if (!This->m_object) + if (This->d()->isReference) { + if (!This->d()->object) return QV4::Encode::undefined(); This->loadReference(); } /* Determine whether we need to modify the sequence */ qint32 newCount = static_cast<qint32>(newLength); - qint32 count = This->m_container.count(); + qint32 count = This->d()->container.count(); if (newCount == count) { return QV4::Encode::undefined(); } 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. */ - This->m_container.reserve(newCount); + This->d()->container.reserve(newCount); while (newCount > count++) { - This->m_container.append(typename Container::value_type()); + This->d()->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--; - This->m_container.removeAt(count); + This->d()->container.removeAt(count); } } /* write back if required. */ - if (This->m_isReference) { + if (This->d()->isReference) { /* write back. already checked that object is non-null, so skip that check here. */ This->storeReference(); } @@ -463,9 +466,9 @@ public: } QVariant toVariant() const - { return QVariant::fromValue<Container>(m_container); } + { return QVariant::fromValue<Container>(d()->container); } - static QVariant toVariant(QV4::ArrayObjectRef array) + static QVariant toVariant(QV4::ArrayObject *array) { QV4::Scope scope(array->engine()); Container result; @@ -479,27 +482,22 @@ public: private: void loadReference() const { - Q_ASSERT(m_object); - Q_ASSERT(m_isReference); - void *a[] = { &m_container, 0 }; - QMetaObject::metacall(m_object, QMetaObject::ReadProperty, m_propertyIndex, a); + Q_ASSERT(d()->object); + Q_ASSERT(d()->isReference); + void *a[] = { &d()->container, 0 }; + QMetaObject::metacall(d()->object, QMetaObject::ReadProperty, d()->propertyIndex, a); } void storeReference() { - Q_ASSERT(m_object); - Q_ASSERT(m_isReference); + Q_ASSERT(d()->object); + Q_ASSERT(d()->isReference); int status = -1; QQmlPropertyPrivate::WriteFlags flags = QQmlPropertyPrivate::DontRemoveBinding; - void *a[] = { &m_container, 0, &status, &flags }; - QMetaObject::metacall(m_object, QMetaObject::WriteProperty, m_propertyIndex, a); + void *a[] = { &d()->container, 0, &status, &flags }; + QMetaObject::metacall(d()->object, QMetaObject::WriteProperty, d()->propertyIndex, a); } - mutable Container m_container; - QPointer<QObject> m_object; - int m_propertyIndex; - bool m_isReference; - static QV4::ReturnedValue getIndexed(QV4::Managed *that, uint index, bool *hasProperty) { return static_cast<QQmlSequence<Container> *>(that)->containerGetIndexed(index, hasProperty); } static void putIndexed(Managed *that, uint index, const QV4::ValueRef value) @@ -510,7 +508,7 @@ private: { return static_cast<QQmlSequence<Container> *>(that)->containerDeleteIndexedProperty(index); } static bool isEqualTo(Managed *that, Managed *other) { return static_cast<QQmlSequence<Container> *>(that)->containerIsEqualTo(other); } - static void advanceIterator(Managed *that, ObjectIterator *it, StringRef name, uint *index, Property *p, PropertyAttributes *attrs) + static void advanceIterator(Managed *that, ObjectIterator *it, String *&name, uint *index, Property *p, PropertyAttributes *attrs) { return static_cast<QQmlSequence<Container> *>(that)->containerAdvanceIterator(it, name, index, p, attrs); } static void destroy(Managed *that) @@ -539,27 +537,22 @@ template<> DEFINE_OBJECT_VTABLE(QQmlRealList); #define REGISTER_QML_SEQUENCE_METATYPE(unused, unused2, SequenceType, unused3) qRegisterMetaType<SequenceType>(#SequenceType); -SequencePrototype::SequencePrototype(InternalClass *ic) - : QV4::Object(ic) -{ - FOREACH_QML_SEQUENCE_TYPE(REGISTER_QML_SEQUENCE_METATYPE) -} -#undef REGISTER_QML_SEQUENCE_METATYPE - void SequencePrototype::init() { + FOREACH_QML_SEQUENCE_TYPE(REGISTER_QML_SEQUENCE_METATYPE) defineDefaultProperty(QStringLiteral("sort"), method_sort, 1); defineDefaultProperty(engine()->id_valueOf, method_valueOf, 0); } +#undef REGISTER_QML_SEQUENCE_METATYPE QV4::ReturnedValue SequencePrototype::method_sort(QV4::CallContext *ctx) { QV4::Scope scope(ctx); - QV4::ScopedObject o(scope, ctx->callData->thisObject); + QV4::ScopedObject o(scope, ctx->d()->callData->thisObject); if (!o || !o->isListType()) return ctx->throwTypeError(); - if (ctx->callData->argc >= 2) + if (ctx->d()->callData->argc >= 2) return o.asReturnedValue(); #define CALL_SORT(SequenceElementType, SequenceElementTypeName, SequenceType, DefaultValue) \ @@ -587,7 +580,7 @@ bool SequencePrototype::isSequenceType(int sequenceTypeId) #define NEW_REFERENCE_SEQUENCE(ElementType, ElementTypeName, SequenceType, unused) \ if (sequenceType == qMetaTypeId<SequenceType>()) { \ - QV4::Scoped<QV4::Object> obj(scope, new (engine->memoryManager) QQml##ElementTypeName##List(engine, object, propertyIndex)); \ + QV4::Scoped<QV4::Object> obj(scope, engine->memoryManager->alloc<QQml##ElementTypeName##List>(engine, object, propertyIndex)); \ return obj.asReturnedValue(); \ } else @@ -605,7 +598,7 @@ ReturnedValue SequencePrototype::newSequence(QV4::ExecutionEngine *engine, int s #define NEW_COPY_SEQUENCE(ElementType, ElementTypeName, SequenceType, unused) \ if (sequenceType == qMetaTypeId<SequenceType>()) { \ - QV4::Scoped<QV4::Object> obj(scope, new (engine->memoryManager) QQml##ElementTypeName##List(engine, v.value<SequenceType >())); \ + QV4::Scoped<QV4::Object> obj(scope, engine->memoryManager->alloc<QQml##ElementTypeName##List>(engine, v.value<SequenceType >())); \ return obj.asReturnedValue(); \ } else @@ -627,7 +620,7 @@ ReturnedValue SequencePrototype::fromVariant(QV4::ExecutionEngine *engine, const return list->toVariant(); \ else -QVariant SequencePrototype::toVariant(ObjectRef object) +QVariant SequencePrototype::toVariant(Object *object) { Q_ASSERT(object->isListType()); FOREACH_QML_SEQUENCE_TYPE(SEQUENCE_TO_VARIANT) { /* else */ return QVariant(); } @@ -660,7 +653,7 @@ QVariant SequencePrototype::toVariant(const QV4::ValueRef array, int typeHint, b return qMetaTypeId<SequenceType>(); \ } else -int SequencePrototype::metaTypeForSequence(QV4::ObjectRef object) +int SequencePrototype::metaTypeForSequence(QV4::Object *object) { FOREACH_QML_SEQUENCE_TYPE(MAP_META_TYPE) /*else*/ { |