aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime/qv4sequenceobject.cpp
diff options
context:
space:
mode:
authorUlf Hermann <[email protected]>2022-05-17 15:50:06 +0200
committerUlf Hermann <[email protected]>2022-06-02 02:42:51 +0200
commite3e8008ec325bdc690fd9600025d66860cac5e62 (patch)
treee82ab867c272e042afc44c627a6f861c2a306418 /src/qml/jsruntime/qv4sequenceobject.cpp
parent7bfbd706b56c426e2683e519543b56426310520f (diff)
Allow retrieval of sequences from QJSValue
As we can store sequence types in QJSValue, we should be able to retrieve them, too. Move the declaration of the QV4::Sequence struct into a header to make it less of a hassle to identify sequences. Change-Id: I3e45bfe193c669107f90cd6c502765c0c9f60fb0 Reviewed-by: Andrei Golubev <[email protected]> Reviewed-by: Sami Shalayel <[email protected]> Reviewed-by: Qt CI Bot <[email protected]> Reviewed-by: Ulf Hermann <[email protected]>
Diffstat (limited to 'src/qml/jsruntime/qv4sequenceobject.cpp')
-rw-r--r--src/qml/jsruntime/qv4sequenceobject.cpp776
1 files changed, 373 insertions, 403 deletions
diff --git a/src/qml/jsruntime/qv4sequenceobject.cpp b/src/qml/jsruntime/qv4sequenceobject.cpp
index c374a9f3cf..fa7bb9d3dd 100644
--- a/src/qml/jsruntime/qv4sequenceobject.cpp
+++ b/src/qml/jsruntime/qv4sequenceobject.cpp
@@ -55,7 +55,34 @@
QT_BEGIN_NAMESPACE
-using namespace QV4;
+namespace QV4 {
+
+DEFINE_OBJECT_VTABLE(Sequence);
+
+static const QMetaSequence *metaSequence(const Heap::Sequence *p)
+{
+ return p->typePrivate->extraData.ld;
+}
+
+template<typename Compare>
+void sortSequence(Sequence *sequence, const Compare &compare)
+{
+ const auto *p = sequence->d();
+ const auto *m = metaSequence(p);
+
+ QSequentialIterable iterable(*m, p->typePrivate->listId, p->container);
+ if (iterable.canRandomAccessIterate()) {
+ std::sort(QSequentialIterable::RandomAccessIterator(iterable.mutableBegin()),
+ QSequentialIterable::RandomAccessIterator(iterable.mutableEnd()),
+ compare);
+ } else if (iterable.canReverseIterate()) {
+ std::sort(QSequentialIterable::BidirectionalIterator(iterable.mutableBegin()),
+ QSequentialIterable::BidirectionalIterator(iterable.mutableEnd()),
+ compare);
+ } else {
+ qWarning() << "Container has no suitable iterator for sorting";
+ }
+}
// helper function to generate valid warnings if errors occur during sequence operations.
static void generateWarning(QV4::ExecutionEngine *v4, const QString& description)
@@ -73,468 +100,413 @@ static void generateWarning(QV4::ExecutionEngine *v4, const QString& description
QQmlEnginePrivate::warning(engine, retn);
}
-namespace QV4 {
+struct SequenceOwnPropertyKeyIterator : ObjectOwnPropertyKeyIterator
+{
+ ~SequenceOwnPropertyKeyIterator() override = default;
+ PropertyKey next(const Object *o, Property *pd = nullptr, PropertyAttributes *attrs = nullptr) override
+ {
+ const Sequence *s = static_cast<const Sequence *>(o);
+
+ if (s->d()->isReference) {
+ if (!s->d()->object)
+ return ObjectOwnPropertyKeyIterator::next(o, pd, attrs);
+ s->loadReference();
+ }
-namespace Heap {
+ if (arrayIndex < quint32(s->size())) {
+ uint index = arrayIndex;
+ ++arrayIndex;
+ if (attrs)
+ *attrs = QV4::Attr_Data;
+ if (pd)
+ pd->value = s->engine()->fromVariant(s->at(index));
+ return PropertyKey::fromArrayIndex(index);
+ }
-struct QV4Sequence : Object {
- void init(const QQmlType &qmlType, const void *container);
- void init(QObject *object, int propertyIndex, const QQmlType &qmlType, bool readOnly);
- void destroy() {
- typePrivate->listId.destroy(container);
- QQmlType::derefHandle(typePrivate);
- object.destroy();
- Object::destroy();
+ return ObjectOwnPropertyKeyIterator::next(o, pd, attrs);
}
+};
+
+struct SequenceCompareFunctor
+{
+ SequenceCompareFunctor(QV4::ExecutionEngine *v4, const QV4::Value &compareFn)
+ : m_v4(v4), m_compareFn(&compareFn)
+ {}
- mutable void *container;
- const QQmlTypePrivate *typePrivate;
- QV4QPointer<QObject> object;
- int propertyIndex;
- bool isReference : 1;
- bool isReadOnly : 1;
+ bool operator()(const QVariant &lhs, const QVariant &rhs)
+ {
+ QV4::Scope scope(m_v4);
+ ScopedFunctionObject compare(scope, m_compareFn);
+ if (!compare)
+ return m_v4->throwTypeError();
+ Value *argv = scope.alloc(2);
+ argv[0] = m_v4->fromVariant(lhs);
+ argv[1] = m_v4->fromVariant(rhs);
+ QV4::ScopedValue result(scope, compare->call(m_v4->globalObject, argv, 2));
+ if (scope.hasException())
+ return false;
+ return result->toNumber() < 0;
+ }
+
+private:
+ QV4::ExecutionEngine *m_v4;
+ const QV4::Value *m_compareFn;
};
-}
+struct SequenceDefaultCompareFunctor
+{
+ bool operator()(const QVariant &lhs, const QVariant &rhs)
+ {
+ return lhs.toString() < rhs.toString();
+ }
+};
-static const QMetaSequence *meta(const Heap::QV4Sequence *p)
+void Heap::Sequence::init(const QQmlType &qmlType, const void *container)
{
- return p->typePrivate->extraData.ld;
+ Object::init();
+
+ Q_ASSERT(qmlType.isSequentialContainer());
+ typePrivate = qmlType.priv();
+ QQmlType::refHandle(typePrivate);
+
+ this->container = typePrivate->listId.create(container);
+ propertyIndex = -1;
+ isReference = false;
+ isReadOnly = false;
+ object.init();
+
+ QV4::Scope scope(internalClass->engine);
+ QV4::Scoped<QV4::Sequence> o(scope, this);
+ o->setArrayType(Heap::ArrayData::Custom);
}
-struct QV4Sequence : public QV4::Object
+void Heap::Sequence::init(
+ QObject *object, int propertyIndex, const QQmlType &qmlType, bool readOnly)
{
- V4_OBJECT2(QV4Sequence, QV4::Object)
- Q_MANAGED_TYPE(V4Sequence)
- V4_PROTOTYPE(sequencePrototype)
- V4_NEEDS_DESTROY
-public:
+ Object::init();
- static const QMetaSequence *metaSequence(const Heap::QV4Sequence *p)
- {
- return p->typePrivate->extraData.ld;
- }
+ Q_ASSERT(qmlType.isSequentialContainer());
+ typePrivate = qmlType.priv();
+ QQmlType::refHandle(typePrivate);
+ container = QMetaType(typePrivate->listId).create();
+ this->propertyIndex = propertyIndex;
+ isReference = true;
+ this->isReadOnly = readOnly;
+ this->object.init(object);
+ QV4::Scope scope(internalClass->engine);
+ QV4::Scoped<QV4::Sequence> o(scope, this);
+ o->setArrayType(Heap::ArrayData::Custom);
+ o->loadReference();
+}
- static const QMetaType valueMetaType(const Heap::QV4Sequence *p)
- {
- return p->typePrivate->typeId;
- }
+void Heap::Sequence::destroy()
+{
+ typePrivate->listId.destroy(container);
+ QQmlType::derefHandle(typePrivate);
+ object.destroy();
+ Object::destroy();
+}
- qsizetype size() const
- {
- const auto *p = d();
- return metaSequence(p)->size(p->container);
- }
+const QMetaType Sequence::valueMetaType(const Heap::Sequence *p)
+{
+ return p->typePrivate->typeId;
+}
- QVariant at(int index) const
- {
- const auto *p = d();
- const QMetaType v = valueMetaType(p);
- QVariant result;
- if (v == QMetaType::fromType<QVariant>()) {
- metaSequence(p)->valueAtIndex(p->container, index, &result);
- } else {
- result = QVariant(v);
- metaSequence(p)->valueAtIndex(p->container, index, result.data());
- }
- return result;
- }
+qsizetype Sequence::size() const
+{
+ const auto *p = d();
+ return metaSequence(p)->size(p->container);
+}
- void append(const QVariant &item)
- {
- const auto *p = d();
- const auto *m = metaSequence(p);
- const QMetaType v = valueMetaType(p);
- if (item.metaType() == v) {
- m->addValueAtEnd(p->container, item.constData());
- } else if (v == QMetaType::fromType<QVariant>()) {
- m->addValueAtEnd(p->container, &item);
- } else {
- QVariant converted = item;
- if (!converted.convert(v))
- converted = QVariant(v);
- m->addValueAtEnd(p->container, converted.constData());
- }
+QVariant Sequence::at(int index) const
+{
+ const auto *p = d();
+ const QMetaType v = valueMetaType(p);
+ QVariant result;
+ if (v == QMetaType::fromType<QVariant>()) {
+ metaSequence(p)->valueAtIndex(p->container, index, &result);
+ } else {
+ result = QVariant(v);
+ metaSequence(p)->valueAtIndex(p->container, index, result.data());
}
+ return result;
+}
- void replace(int index, const QVariant &item)
- {
- const auto *p = d();
- const auto *m = metaSequence(p);
- const QMetaType v = valueMetaType(p);
- if (item.metaType() == v) {
- m->setValueAtIndex(p->container, index, item.constData());
- } else if (v == QMetaType::fromType<QVariant>()) {
- m->setValueAtIndex(p->container, index, &item);
- } else {
- QVariant converted = item;
- if (!converted.convert(v))
- converted = QVariant(v);
- m->setValueAtIndex(p->container, index, converted.constData());
- }
+void Sequence::append(const QVariant &item)
+{
+ const auto *p = d();
+ const auto *m = metaSequence(p);
+ const QMetaType v = valueMetaType(p);
+ if (item.metaType() == v) {
+ m->addValueAtEnd(p->container, item.constData());
+ } else if (v == QMetaType::fromType<QVariant>()) {
+ m->addValueAtEnd(p->container, &item);
+ } else {
+ QVariant converted = item;
+ if (!converted.convert(v))
+ converted = QVariant(v);
+ m->addValueAtEnd(p->container, converted.constData());
}
+}
- template<typename Compare>
- void sort(const Compare &compare)
- {
- const auto *p = d();
- const auto *m = metaSequence(p);
-
- QSequentialIterable iterable(*m, p->typePrivate->listId, p->container);
- if (iterable.canRandomAccessIterate()) {
- std::sort(QSequentialIterable::RandomAccessIterator(iterable.mutableBegin()),
- QSequentialIterable::RandomAccessIterator(iterable.mutableEnd()),
- compare);
- } else if (iterable.canReverseIterate()) {
- std::sort(QSequentialIterable::BidirectionalIterator(iterable.mutableBegin()),
- QSequentialIterable::BidirectionalIterator(iterable.mutableEnd()),
- compare);
- } else {
- qWarning() << "Container has no suitable iterator for sorting";
- }
+void Sequence::replace(int index, const QVariant &item)
+{
+ const auto *p = d();
+ const auto *m = metaSequence(p);
+ const QMetaType v = valueMetaType(p);
+ if (item.metaType() == v) {
+ m->setValueAtIndex(p->container, index, item.constData());
+ } else if (v == QMetaType::fromType<QVariant>()) {
+ m->setValueAtIndex(p->container, index, &item);
+ } else {
+ QVariant converted = item;
+ if (!converted.convert(v))
+ converted = QVariant(v);
+ m->setValueAtIndex(p->container, index, converted.constData());
}
+}
- void removeLast(int num)
- {
- const auto *p = d();
- const auto *m = metaSequence(p);
-
- if (m->canEraseRangeAtIterator() && m->hasRandomAccessIterator() && num > 1) {
- void *i = m->end(p->container);
- m->advanceIterator(i, -num);
- void *j = m->end(p->container);
- m->eraseRangeAtIterator(p->container, i, j);
- m->destroyIterator(i);
- m->destroyIterator(j);
- } else {
- for (int i = 0; i < num; ++i)
- m->removeValueAtEnd(p->container);
- }
+void Sequence::removeLast(int num)
+{
+ const auto *p = d();
+ const auto *m = metaSequence(p);
+
+ if (m->canEraseRangeAtIterator() && m->hasRandomAccessIterator() && num > 1) {
+ void *i = m->end(p->container);
+ m->advanceIterator(i, -num);
+ void *j = m->end(p->container);
+ m->eraseRangeAtIterator(p->container, i, j);
+ m->destroyIterator(i);
+ m->destroyIterator(j);
+ } else {
+ for (int i = 0; i < num; ++i)
+ m->removeValueAtEnd(p->container);
}
+}
- QVariant toVariant()
- {
- const auto *p = d();
- return QVariant(p->typePrivate->listId, p->container);
- }
+QVariant Sequence::toVariant() const
+{
+ const auto *p = d();
+ return QVariant(p->typePrivate->listId, p->container);
+}
- // ### Qt 7 use qsizetype instead.
- QV4::ReturnedValue containerGetIndexed(uint index, bool *hasProperty) const
- {
- /* Qt containers have int (rather than uint) allowable indexes. */
- if (index > INT_MAX) {
- generateWarning(engine(), QLatin1String("Index out of range during indexed get"));
+ReturnedValue Sequence::containerGetIndexed(uint index, bool *hasProperty) const
+{
+ /* Qt containers have int (rather than uint) allowable indexes. */
+ if (index > INT_MAX) {
+ generateWarning(engine(), QLatin1String("Index out of range during indexed get"));
+ if (hasProperty)
+ *hasProperty = false;
+ return Encode::undefined();
+ }
+ if (d()->isReference) {
+ if (!d()->object) {
if (hasProperty)
*hasProperty = false;
return Encode::undefined();
}
- if (d()->isReference) {
- if (!d()->object) {
- if (hasProperty)
- *hasProperty = false;
- return Encode::undefined();
- }
- loadReference();
- }
- if (index < quint32(size())) {
- if (hasProperty)
- *hasProperty = true;
- return engine()->fromVariant(at(index));
- }
+ loadReference();
+ }
+ if (index < quint32(size())) {
if (hasProperty)
- *hasProperty = false;
- return Encode::undefined();
+ *hasProperty = true;
+ return engine()->fromVariant(at(index));
}
+ if (hasProperty)
+ *hasProperty = false;
+ return Encode::undefined();
+}
- // ### Qt 7 use qsizetype instead.
- bool containerPutIndexed(uint index, const QV4::Value &value)
- {
- if (internalClass()->engine->hasException)
- return false;
+bool Sequence::containerPutIndexed(uint index, const Value &value)
+{
+ if (internalClass()->engine->hasException)
+ return false;
- /* Qt containers have int (rather than uint) allowable indexes. */
- if (index > INT_MAX) {
- generateWarning(engine(), QLatin1String("Index out of range during indexed set"));
- return false;
- }
+ /* Qt containers have int (rather than uint) allowable indexes. */
+ if (index > INT_MAX) {
+ generateWarning(engine(), QLatin1String("Index out of range during indexed set"));
+ return false;
+ }
- if (d()->isReadOnly) {
- engine()->throwTypeError(QLatin1String("Cannot insert into a readonly container"));
+ if (d()->isReadOnly) {
+ engine()->throwTypeError(QLatin1String("Cannot insert into a readonly container"));
+ return false;
+ }
+
+ if (d()->isReference) {
+ if (!d()->object)
return false;
- }
+ loadReference();
+ }
- if (d()->isReference) {
- if (!d()->object)
- return false;
- loadReference();
- }
+ quint32 count = quint32(size());
+ const QMetaType valueType = valueMetaType(d());
+ const QVariant element = engine()->toVariant(value, valueType, false);
- quint32 count = quint32(size());
- const QMetaType valueType = valueMetaType(d());
- const QVariant element = engine()->toVariant(value, valueType, false);
-
- if (index == count) {
- append(element);
- } else if (index < count) {
- replace(index, element);
- } else {
- /* according to ECMA262r3 we need to insert */
- /* the value at the given index, increasing length to index+1. */
- while (index > count++) {
- append(valueType == QMetaType::fromType<QVariant>()
- ? QVariant()
- : QVariant(valueType));
- }
- append(element);
+ if (index == count) {
+ append(element);
+ } else if (index < count) {
+ replace(index, element);
+ } else {
+ /* according to ECMA262r3 we need to insert */
+ /* the value at the given index, increasing length to index+1. */
+ while (index > count++) {
+ append(valueType == QMetaType::fromType<QVariant>()
+ ? QVariant()
+ : QVariant(valueType));
}
-
- if (d()->isReference)
- storeReference();
- return true;
+ append(element);
}
- QV4::PropertyAttributes containerQueryIndexed(uint index) const
- {
- /* Qt containers have int (rather than uint) allowable indexes. */
- if (index > INT_MAX) {
- generateWarning(engine(), QLatin1String("Index out of range during indexed query"));
+ if (d()->isReference)
+ storeReference();
+ return true;
+}
+
+PropertyAttributes Sequence::containerQueryIndexed(uint index) const
+{
+ /* Qt containers have int (rather than uint) allowable indexes. */
+ if (index > INT_MAX) {
+ generateWarning(engine(), QLatin1String("Index out of range during indexed query"));
+ return QV4::Attr_Invalid;
+ }
+ if (d()->isReference) {
+ if (!d()->object)
return QV4::Attr_Invalid;
- }
- if (d()->isReference) {
- if (!d()->object)
- return QV4::Attr_Invalid;
- loadReference();
- }
- return (index < quint32(size())) ? QV4::Attr_Data : QV4::Attr_Invalid;
+ loadReference();
}
+ return (index < quint32(size())) ? QV4::Attr_Data : QV4::Attr_Invalid;
+}
- struct OwnPropertyKeyIterator : ObjectOwnPropertyKeyIterator
- {
- ~OwnPropertyKeyIterator() override = default;
- PropertyKey next(const Object *o, Property *pd = nullptr, PropertyAttributes *attrs = nullptr) override
- {
- const QV4Sequence *s = static_cast<const QV4Sequence *>(o);
-
- if (s->d()->isReference) {
- if (!s->d()->object)
- return ObjectOwnPropertyKeyIterator::next(o, pd, attrs);
- s->loadReference();
- }
-
- if (arrayIndex < quint32(s->size())) {
- uint index = arrayIndex;
- ++arrayIndex;
- if (attrs)
- *attrs = QV4::Attr_Data;
- if (pd)
- pd->value = s->engine()->fromVariant(s->at(index));
- return PropertyKey::fromArrayIndex(index);
- }
-
- return ObjectOwnPropertyKeyIterator::next(o, pd, attrs);
- }
- };
-
- static OwnPropertyKeyIterator *containerOwnPropertyKeys(const Object *m, Value *target)
- {
- *target = *m;
- return new OwnPropertyKeyIterator;
- }
+SequenceOwnPropertyKeyIterator *containerOwnPropertyKeys(const Object *m, Value *target)
+{
+ *target = *m;
+ return new SequenceOwnPropertyKeyIterator;
+}
- bool containerDeleteIndexedProperty(uint index)
- {
- /* Qt containers have int (rather than uint) allowable indexes. */
- if (index > INT_MAX)
- return false;
- if (d()->isReadOnly)
+bool Sequence::containerDeleteIndexedProperty(uint index)
+{
+ /* Qt containers have int (rather than uint) allowable indexes. */
+ if (index > INT_MAX)
+ return false;
+ if (d()->isReadOnly)
+ return false;
+ if (d()->isReference) {
+ if (!d()->object)
return false;
- if (d()->isReference) {
- if (!d()->object)
- return false;
- loadReference();
- }
+ loadReference();
+ }
- if (index >= quint32(size()))
- return false;
+ if (index >= quint32(size()))
+ return false;
- /* according to ECMA262r3 it should be Undefined, */
- /* but we cannot, so we insert a default-value instead. */
- replace(index, QVariant());
+ /* according to ECMA262r3 it should be Undefined, */
+ /* but we cannot, so we insert a default-value instead. */
+ replace(index, QVariant());
- if (d()->isReference)
- storeReference();
+ if (d()->isReference)
+ storeReference();
- return true;
- }
+ return true;
+}
- bool containerIsEqualTo(Managed *other)
- {
- if (!other)
- return false;
- QV4Sequence *otherSequence = other->as<QV4Sequence>();
- if (!otherSequence)
- return false;
- 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;
- }
+bool Sequence::containerIsEqualTo(Managed *other)
+{
+ if (!other)
+ return false;
+ Sequence *otherSequence = other->as<Sequence>();
+ if (!otherSequence)
return false;
+ 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;
+}
- struct DefaultCompareFunctor
- {
- bool operator()(const QVariant &lhs, const QVariant &rhs)
- {
- return lhs.toString() < rhs.toString();
- }
- };
-
- struct CompareFunctor
- {
- CompareFunctor(QV4::ExecutionEngine *v4, const QV4::Value &compareFn)
- : m_v4(v4), m_compareFn(&compareFn)
- {}
-
- bool operator()(const QVariant &lhs, const QVariant &rhs)
- {
- QV4::Scope scope(m_v4);
- ScopedFunctionObject compare(scope, m_compareFn);
- if (!compare)
- return m_v4->throwTypeError();
- Value *argv = scope.alloc(2);
- argv[0] = m_v4->fromVariant(lhs);
- argv[1] = m_v4->fromVariant(rhs);
- QV4::ScopedValue result(scope, compare->call(m_v4->globalObject, argv, 2));
- if (scope.hasException())
- return false;
- return result->toNumber() < 0;
- }
-
- private:
- QV4::ExecutionEngine *m_v4;
- const QV4::Value *m_compareFn;
- };
-
- bool sort(const FunctionObject *f, const Value *, const Value *argv, int argc)
- {
- if (d()->isReadOnly)
+bool Sequence::sort(const FunctionObject *f, const Value *, const Value *argv, int argc)
+{
+ if (d()->isReadOnly)
+ return false;
+ if (d()->isReference) {
+ if (!d()->object)
return false;
- if (d()->isReference) {
- if (!d()->object)
- return false;
- loadReference();
- }
-
- if (argc == 1 && argv[0].as<FunctionObject>())
- sort(CompareFunctor(f->engine(), argv[0]));
- else
- sort(DefaultCompareFunctor());
-
- if (d()->isReference)
- storeReference();
-
- return true;
+ loadReference();
}
- void* getRawContainerPtr() const
- { return d()->container; }
+ if (argc == 1 && argv[0].as<FunctionObject>())
+ sortSequence(this, SequenceCompareFunctor(f->engine(), argv[0]));
+ else
+ sortSequence(this, SequenceDefaultCompareFunctor());
- void loadReference() const
- {
- Q_ASSERT(d()->object);
- Q_ASSERT(d()->isReference);
- void *a[] = { d()->container, nullptr };
- QMetaObject::metacall(d()->object, QMetaObject::ReadProperty, d()->propertyIndex, a);
- }
+ if (d()->isReference)
+ storeReference();
- void storeReference()
- {
- Q_ASSERT(d()->object);
- Q_ASSERT(d()->isReference);
- int status = -1;
- QQmlPropertyData::WriteFlags flags = QQmlPropertyData::DontRemoveBinding;
- void *a[] = { d()->container, nullptr, &status, &flags };
- QMetaObject::metacall(d()->object, QMetaObject::WriteProperty, d()->propertyIndex, a);
- }
-
- static QV4::ReturnedValue virtualGet(const QV4::Managed *that, PropertyKey id, const Value *receiver, bool *hasProperty)
- {
- if (!id.isArrayIndex())
- return Object::virtualGet(that, id, receiver, hasProperty);
- return static_cast<const QV4Sequence *>(that)->containerGetIndexed(id.asArrayIndex(), hasProperty);
- }
- static bool virtualPut(Managed *that, PropertyKey id, const QV4::Value &value, Value *receiver)
- {
- if (id.isArrayIndex())
- return static_cast<QV4Sequence *>(that)->containerPutIndexed(id.asArrayIndex(), value);
- return Object::virtualPut(that, id, value, receiver);
- }
- static QV4::PropertyAttributes queryIndexed(const QV4::Managed *that, uint index)
- { return static_cast<const QV4Sequence *>(that)->containerQueryIndexed(index); }
- static bool virtualDeleteProperty(QV4::Managed *that, PropertyKey id)
- {
- if (id.isArrayIndex()) {
- uint index = id.asArrayIndex();
- return static_cast<QV4Sequence *>(that)->containerDeleteIndexedProperty(index);
- }
- return Object::virtualDeleteProperty(that, id);
- }
- static bool virtualIsEqualTo(Managed *that, Managed *other)
- { return static_cast<QV4Sequence *>(that)->containerIsEqualTo(other); }
- static QV4::OwnPropertyKeyIterator *virtualOwnPropertyKeys(const Object *m, Value *target)
- { return static_cast<const QV4Sequence *>(m)->containerOwnPropertyKeys(m, target);}
-};
+ return true;
+}
+void *Sequence::getRawContainerPtr() const
+{ return d()->container; }
-void Heap::QV4Sequence::init(const QQmlType &qmlType, const void *container)
+void Sequence::loadReference() const
{
- Object::init();
-
- Q_ASSERT(qmlType.isSequentialContainer());
- typePrivate = qmlType.priv();
- QQmlType::refHandle(typePrivate);
+ Q_ASSERT(d()->object);
+ Q_ASSERT(d()->isReference);
+ void *a[] = { d()->container, nullptr };
+ QMetaObject::metacall(d()->object, QMetaObject::ReadProperty, d()->propertyIndex, a);
+}
- this->container = typePrivate->listId.create(container);
- propertyIndex = -1;
- isReference = false;
- isReadOnly = false;
- object.init();
+void Sequence::storeReference()
+{
+ Q_ASSERT(d()->object);
+ Q_ASSERT(d()->isReference);
+ int status = -1;
+ QQmlPropertyData::WriteFlags flags = QQmlPropertyData::DontRemoveBinding;
+ void *a[] = { d()->container, nullptr, &status, &flags };
+ QMetaObject::metacall(d()->object, QMetaObject::WriteProperty, d()->propertyIndex, a);
+}
- QV4::Scope scope(internalClass->engine);
- QV4::Scoped<QV4::QV4Sequence> o(scope, this);
- o->setArrayType(Heap::ArrayData::Custom);
+ReturnedValue Sequence::virtualGet(const Managed *that, PropertyKey id, const Value *receiver, bool *hasProperty)
+{
+ if (!id.isArrayIndex())
+ return Object::virtualGet(that, id, receiver, hasProperty);
+ return static_cast<const Sequence *>(that)->containerGetIndexed(id.asArrayIndex(), hasProperty);
}
-void Heap::QV4Sequence::init(QObject *object, int propertyIndex, const QQmlType &qmlType,
- bool readOnly)
+bool Sequence::virtualPut(Managed *that, PropertyKey id, const Value &value, Value *receiver)
{
- Object::init();
+ if (id.isArrayIndex())
+ return static_cast<Sequence *>(that)->containerPutIndexed(id.asArrayIndex(), value);
+ return Object::virtualPut(that, id, value, receiver);
+}
- Q_ASSERT(qmlType.isSequentialContainer());
- typePrivate = qmlType.priv();
- QQmlType::refHandle(typePrivate);
- container = QMetaType(typePrivate->listId).create();
- this->propertyIndex = propertyIndex;
- isReference = true;
- this->isReadOnly = readOnly;
- this->object.init(object);
- QV4::Scope scope(internalClass->engine);
- QV4::Scoped<QV4::QV4Sequence> o(scope, this);
- o->setArrayType(Heap::ArrayData::Custom);
- o->loadReference();
+PropertyAttributes Sequence::queryIndexed(const Managed *that, uint index)
+{ return static_cast<const Sequence *>(that)->containerQueryIndexed(index); }
+
+bool Sequence::virtualDeleteProperty(Managed *that, PropertyKey id)
+{
+ if (id.isArrayIndex()) {
+ uint index = id.asArrayIndex();
+ return static_cast<Sequence *>(that)->containerDeleteIndexedProperty(index);
+ }
+ return Object::virtualDeleteProperty(that, id);
}
+bool Sequence::virtualIsEqualTo(Managed *that, Managed *other)
+{
+ return static_cast<Sequence *>(that)->containerIsEqualTo(other);
}
-namespace QV4 {
-DEFINE_OBJECT_VTABLE(QV4Sequence);
+OwnPropertyKeyIterator *Sequence::virtualOwnPropertyKeys(const Object *m, Value *target)
+{
+ return containerOwnPropertyKeys(m, target);
}
static QV4::ReturnedValue method_get_length(const FunctionObject *b, const Value *thisObject, const Value *, int)
{
QV4::Scope scope(b);
- QV4::Scoped<QV4Sequence> This(scope, thisObject->as<QV4Sequence>());
+ QV4::Scoped<Sequence> This(scope, thisObject->as<Sequence>());
if (!This)
THROW_TYPE_ERROR();
@@ -549,7 +521,7 @@ static QV4::ReturnedValue method_get_length(const FunctionObject *b, const Value
static QV4::ReturnedValue method_set_length(const FunctionObject *f, const Value *thisObject, const Value *argv, int argc)
{
QV4::Scope scope(f);
- QV4::Scoped<QV4Sequence> This(scope, thisObject->as<QV4Sequence>());
+ QV4::Scoped<Sequence> This(scope, thisObject->as<Sequence>());
if (!This)
THROW_TYPE_ERROR();
@@ -575,7 +547,7 @@ static QV4::ReturnedValue method_set_length(const FunctionObject *f, const Value
if (newCount == count) {
RETURN_UNDEFINED();
} else if (newCount > count) {
- const QMetaType valueMetaType = meta(This->d())->valueMetaType();
+ const QMetaType valueMetaType = metaSequence(This->d())->valueMetaType();
/* according to ECMA262r3 we need to insert */
/* undefined values increasing length to newLength. */
/* We cannot, so we insert default-values instead. */
@@ -617,7 +589,7 @@ ReturnedValue SequencePrototype::method_sort(const FunctionObject *b, const Valu
if (argc >= 2)
return o.asReturnedValue();
- if (auto *s = o->as<QV4Sequence>()) {
+ if (auto *s = o->as<Sequence>()) {
if (!s->sort(b, thisObject, argv, argc))
THROW_TYPE_ERROR();
}
@@ -638,7 +610,7 @@ ReturnedValue SequencePrototype::newSequence(
const QQmlType qmlType = QQmlMetaType::qmlListType(sequenceType);
if (qmlType.isSequentialContainer()) {
*succeeded = true;
- QV4::ScopedObject obj(scope, engine->memoryManager->allocate<QV4Sequence>(
+ QV4::ScopedObject obj(scope, engine->memoryManager->allocate<Sequence>(
object, propertyIndex, qmlType, readOnly));
return obj.asReturnedValue();
}
@@ -664,7 +636,7 @@ ReturnedValue SequencePrototype::fromData(ExecutionEngine *engine, QMetaType typ
const QQmlType qmlType = QQmlMetaType::qmlListType(type);
if (qmlType.isSequentialContainer()) {
*succeeded = true;
- QV4::ScopedObject obj(scope, engine->memoryManager->allocate<QV4Sequence>(qmlType, data));
+ QV4::ScopedObject obj(scope, engine->memoryManager->allocate<Sequence>(qmlType, data));
return obj.asReturnedValue();
}
@@ -672,10 +644,10 @@ ReturnedValue SequencePrototype::fromData(ExecutionEngine *engine, QMetaType typ
return Encode::undefined();
}
-QVariant SequencePrototype::toVariant(Object *object)
+QVariant SequencePrototype::toVariant(const Sequence *object)
{
Q_ASSERT(object->isListType());
- return object->as<QV4Sequence>()->toVariant();
+ return object->toVariant();
}
QVariant SequencePrototype::toVariant(const QV4::Value &array, QMetaType typeHint, bool *succeeded)
@@ -721,22 +693,20 @@ QVariant SequencePrototype::toVariant(const QV4::Value &array, QMetaType typeHin
return QVariant();
}
-void *SequencePrototype::getRawContainerPtr(const Object *object, QMetaType typeHint)
+void *SequencePrototype::getRawContainerPtr(const Sequence *object, QMetaType typeHint)
{
- if (auto *s = object->as<QV4Sequence>()) {
- if (s->d()->typePrivate->listId == typeHint)
- return s->getRawContainerPtr();
- }
+ if (object->d()->typePrivate->listId == typeHint)
+ return object->getRawContainerPtr();
return nullptr;
}
-QMetaType SequencePrototype::metaTypeForSequence(const QV4::Object *object)
+QMetaType SequencePrototype::metaTypeForSequence(const Sequence *object)
{
- if (auto *s = object->as<QV4Sequence>())
- return s->d()->typePrivate->listId;
- return QMetaType();
+ return object->d()->typePrivate->listId;
}
+} // namespace QV4
+
QT_END_NAMESPACE
#include "moc_qv4sequenceobject_p.cpp"