aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/jsruntime')
-rw-r--r--src/qml/jsruntime/qv4arraydata.cpp73
-rw-r--r--src/qml/jsruntime/qv4arraydata_p.h68
-rw-r--r--src/qml/jsruntime/qv4arrayiterator.cpp1
-rw-r--r--src/qml/jsruntime/qv4arrayobject.cpp39
-rw-r--r--src/qml/jsruntime/qv4engine.cpp2
-rw-r--r--src/qml/jsruntime/qv4managed.cpp3
-rw-r--r--src/qml/jsruntime/qv4managed_p.h9
-rw-r--r--src/qml/jsruntime/qv4scopedvalue_p.h7
-rw-r--r--src/qml/jsruntime/qv4sequenceobject.cpp4
9 files changed, 111 insertions, 95 deletions
diff --git a/src/qml/jsruntime/qv4arraydata.cpp b/src/qml/jsruntime/qv4arraydata.cpp
index 5c62e806f7..6e01c50048 100644
--- a/src/qml/jsruntime/qv4arraydata.cpp
+++ b/src/qml/jsruntime/qv4arraydata.cpp
@@ -587,21 +587,6 @@ void ArrayData::insert(Object *o, uint index, const Value *v, bool isAccessor)
s->setArrayData(o->engine(), n->value + Object::SetterOffset, v[Object::SetterOffset]);
}
-
-class ArrayElementLessThan
-{
-public:
- inline ArrayElementLessThan(ExecutionEngine *engine, const Value &comparefn)
- : m_engine(engine), m_comparefn(comparefn) {}
-
- bool operator()(Value v1, Value v2) const;
-
-private:
- ExecutionEngine *m_engine;
- const Value &m_comparefn;
-};
-
-
bool ArrayElementLessThan::operator()(Value v1, Value v2) const
{
Scope scope(m_engine);
@@ -634,60 +619,6 @@ bool ArrayElementLessThan::operator()(Value v1, Value v2) const
return p1s->toQString() < p2s->toQString();
}
-template <typename RandomAccessIterator, typename T, typename LessThan>
-void sortHelper(RandomAccessIterator start, RandomAccessIterator end, const T &t, LessThan lessThan)
-{
-top:
- int span = int(end - start);
- if (span < 2)
- return;
-
- --end;
- RandomAccessIterator low = start, high = end - 1;
- RandomAccessIterator pivot = start + span / 2;
-
- if (lessThan(*end, *start))
- qSwap(*end, *start);
- if (span == 2)
- return;
-
- if (lessThan(*pivot, *start))
- qSwap(*pivot, *start);
- if (lessThan(*end, *pivot))
- qSwap(*end, *pivot);
- if (span == 3)
- return;
-
- qSwap(*pivot, *end);
-
- while (low < high) {
- while (low < high && lessThan(*low, *end))
- ++low;
-
- while (high > low && lessThan(*end, *high))
- --high;
-
- if (low < high) {
- qSwap(*low, *high);
- ++low;
- --high;
- } else {
- break;
- }
- }
-
- if (lessThan(*low, *end))
- ++low;
-
- qSwap(*end, *low);
- sortHelper(start, low, t, lessThan);
-
- start = low + 1;
- ++end;
- goto top;
-}
-
-
void ArrayData::sort(ExecutionEngine *engine, Object *thisObject, const Value &comparefn, uint len)
{
if (!len)
@@ -778,10 +709,10 @@ void ArrayData::sort(ExecutionEngine *engine, Object *thisObject, const Value &c
}
- ArrayElementLessThan lessThan(engine, static_cast<const FunctionObject &>(comparefn));
+ ArrayElementLessThan lessThan(engine, comparefn);
Value *begin = thisObject->arrayData()->values.values;
- sortHelper(begin, begin + len, *begin, lessThan);
+ sortHelper(begin, begin + len, lessThan);
#ifdef CHECK_SPARSE_ARRAYS
thisObject->initSparseArray();
diff --git a/src/qml/jsruntime/qv4arraydata_p.h b/src/qml/jsruntime/qv4arraydata_p.h
index 25792f7076..a7ab1f4a71 100644
--- a/src/qml/jsruntime/qv4arraydata_p.h
+++ b/src/qml/jsruntime/qv4arraydata_p.h
@@ -231,6 +231,74 @@ struct Q_QML_EXPORT SparseArrayData : public ArrayData
static uint length(const Heap::ArrayData *d);
};
+class ArrayElementLessThan
+{
+public:
+ inline ArrayElementLessThan(ExecutionEngine *engine, const Value &comparefn)
+ : m_engine(engine), m_comparefn(comparefn) {}
+
+ bool operator()(Value v1, Value v2) const;
+
+private:
+ ExecutionEngine *m_engine;
+ const Value &m_comparefn;
+};
+
+template <typename RandomAccessIterator, typename LessThan>
+void sortHelper(RandomAccessIterator start, RandomAccessIterator end, LessThan lessThan)
+{
+top:
+ using std::swap;
+
+ int span = int(end - start);
+ if (span < 2)
+ return;
+
+ --end;
+ RandomAccessIterator low = start, high = end - 1;
+ RandomAccessIterator pivot = start + span / 2;
+
+ if (lessThan(*end, *start))
+ swap(*end, *start);
+ if (span == 2)
+ return;
+
+ if (lessThan(*pivot, *start))
+ swap(*pivot, *start);
+ if (lessThan(*end, *pivot))
+ swap(*end, *pivot);
+ if (span == 3)
+ return;
+
+ swap(*pivot, *end);
+
+ while (low < high) {
+ while (low < high && lessThan(*low, *end))
+ ++low;
+
+ while (high > low && lessThan(*end, *high))
+ --high;
+
+ if (low < high) {
+ swap(*low, *high);
+ ++low;
+ --high;
+ } else {
+ break;
+ }
+ }
+
+ if (lessThan(*low, *end))
+ ++low;
+
+ swap(*end, *low);
+ sortHelper(start, low, lessThan);
+
+ start = low + 1;
+ ++end;
+ goto top;
+}
+
namespace Heap {
inline uint ArrayData::mappedIndex(uint index) const
diff --git a/src/qml/jsruntime/qv4arrayiterator.cpp b/src/qml/jsruntime/qv4arrayiterator.cpp
index 80e7506143..15e0bf4e4c 100644
--- a/src/qml/jsruntime/qv4arrayiterator.cpp
+++ b/src/qml/jsruntime/qv4arrayiterator.cpp
@@ -36,7 +36,6 @@ ReturnedValue ArrayIteratorPrototype::method_next(const FunctionObject *b, const
quint32 index = thisObject->d()->nextIndex;
IteratorKind itemKind = thisObject->d()->iterationKind;
- Scoped<TypedArray> ta(scope, a->as<TypedArray>());
quint32 len = a->getLength();
if (index >= len) {
diff --git a/src/qml/jsruntime/qv4arrayobject.cpp b/src/qml/jsruntime/qv4arrayobject.cpp
index 67cf5c2fdd..ebe70406cb 100644
--- a/src/qml/jsruntime/qv4arrayobject.cpp
+++ b/src/qml/jsruntime/qv4arrayobject.cpp
@@ -398,7 +398,7 @@ ReturnedValue ArrayPrototype::method_concat(const FunctionObject *b, const Value
return scope.engine->throwTypeError();
}
}
- } else if (eltAsObj && eltAsObj->isListType()) {
+ } else if (eltAsObj && eltAsObj->isArrayLike()) {
const uint startIndex = result->getLength();
for (int i = 0, len = eltAsObj->getLength(); i < len; ++i) {
entry = eltAsObj->get(i);
@@ -1188,31 +1188,38 @@ ReturnedValue ArrayPrototype::method_fill(const FunctionObject *b, const Value *
if (!instance)
RETURN_UNDEFINED();
- uint len = instance->getLength();
- int relativeStart = argc > 1 ? argv[1].toInteger() : 0;
- int relativeEnd = len;
- if (argc > 2 && !argv[2].isUndefined()) {
+ const qsizetype len = instance->getLength();
+ Q_ASSERT(len >= 0);
+
+ const qsizetype relativeStart = argc > 1 ? argv[1].toInteger() : 0;
+ qsizetype relativeEnd = len;
+ if (argc > 2 && !argv[2].isUndefined())
relativeEnd = argv[2].toInteger();
- }
- uint k = 0;
- uint fin = 0;
+
+ qsizetype k = 0;
+ qsizetype fin = 0;
if (relativeStart < 0) {
- k = std::max(len+relativeStart, uint(0));
+ if (relativeStart > -len)
+ k = std::max(len + relativeStart, qsizetype(0));
} else {
- k = std::min(uint(relativeStart), len);
+ k = std::min(relativeStart, len);
}
+ Q_ASSERT(k >= 0);
if (relativeEnd < 0) {
- fin = std::max(len + relativeEnd, uint(0));
+ if (relativeEnd > -len)
+ fin = std::max(len + relativeEnd, qsizetype(0));
} else {
- fin = std::min(uint(relativeEnd), len);
+ fin = std::min(relativeEnd, len);
}
+ Q_ASSERT(fin >= 0);
- while (k < fin) {
- instance->setIndexed(k, argv[0], QV4::Object::DoThrowOnRejection);
- k++;
- }
+ if (sizeof(qsizetype) > sizeof(uint) && fin > qsizetype(std::numeric_limits<uint>::max()))
+ return scope.engine->throwRangeError(QString::fromLatin1("Array length out of range."));
+
+ for (; k < fin; ++k)
+ instance->setIndexed(uint(k), argv[0], QV4::Object::DoThrowOnRejection);
return instance.asReturnedValue();
}
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index 63fafeda60..c6c504154b 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -696,7 +696,7 @@ ExecutionEngine::ExecutionEngine(QJSEngine *jsEngine)
static_cast<NumberPrototype *>(numberPrototype())->init(this, numberCtor());
static_cast<BooleanPrototype *>(booleanPrototype())->init(this, booleanCtor());
static_cast<ArrayPrototype *>(arrayPrototype())->init(this, arrayCtor());
- static_cast<PropertyListPrototype *>(propertyListPrototype())->init(this);
+ static_cast<PropertyListPrototype *>(propertyListPrototype())->init();
static_cast<DatePrototype *>(datePrototype())->init(this, dateCtor());
static_cast<FunctionPrototype *>(functionPrototype())->init(this, functionCtor());
static_cast<GeneratorPrototype *>(generatorPrototype())->init(this, generatorFunctionCtor());
diff --git a/src/qml/jsruntime/qv4managed.cpp b/src/qml/jsruntime/qv4managed.cpp
index 3c44ed525b..647b858f0f 100644
--- a/src/qml/jsruntime/qv4managed.cpp
+++ b/src/qml/jsruntime/qv4managed.cpp
@@ -104,6 +104,9 @@ QString Managed::className() const
case Type_V4Sequence:
s = "V4Sequence";
break;
+ case Type_QmlListProperty:
+ s = "QML List";
+ break;
}
return QString::fromLatin1(s);
}
diff --git a/src/qml/jsruntime/qv4managed_p.h b/src/qml/jsruntime/qv4managed_p.h
index 4865b75e2f..299d4b4196 100644
--- a/src/qml/jsruntime/qv4managed_p.h
+++ b/src/qml/jsruntime/qv4managed_p.h
@@ -120,7 +120,9 @@ public:
Type_ForInIterator,
Type_RegExp,
- Type_V4Sequence
+ Type_V4Sequence,
+ Type_QmlListProperty,
+
};
Q_MANAGED_TYPE(Invalid)
@@ -128,8 +130,9 @@ public:
const VTable *vtable() const { return d()->internalClass->vtable; }
inline ExecutionEngine *engine() const { return internalClass()->engine; }
- bool isListType() const { return d()->internalClass->vtable->type == Type_V4Sequence; }
- bool isArrayLike() const { return isArrayObject() || isListType(); }
+ bool isV4SequenceType() const { return d()->internalClass->vtable->type == Type_V4Sequence; }
+ bool isQmlListPropertyType() const { return d()->internalClass->vtable->type == Type_QmlListProperty; }
+ bool isArrayLike() const { return isArrayObject() || isV4SequenceType() || isQmlListPropertyType(); }
bool isArrayObject() const { return d()->internalClass->vtable->type == Type_ArrayObject; }
bool isStringObject() const { return d()->internalClass->vtable->type == Type_StringObject; }
diff --git a/src/qml/jsruntime/qv4scopedvalue_p.h b/src/qml/jsruntime/qv4scopedvalue_p.h
index 09e8b60c91..fd68fcc1b3 100644
--- a/src/qml/jsruntime/qv4scopedvalue_p.h
+++ b/src/qml/jsruntime/qv4scopedvalue_p.h
@@ -32,9 +32,14 @@ namespace QV4 {
struct ScopedValue;
+inline bool hasExceptionOrIsInterrupted(ExecutionEngine *engine)
+{
+ return engine->hasException || engine->isInterrupted.loadRelaxed();
+}
+
#define CHECK_EXCEPTION() \
do { \
- if (scope.hasException() || scope.engine->isInterrupted.loadRelaxed()) { \
+ if (hasExceptionOrIsInterrupted(scope.engine)) { \
return QV4::Encode::undefined(); \
} \
} while (false)
diff --git a/src/qml/jsruntime/qv4sequenceobject.cpp b/src/qml/jsruntime/qv4sequenceobject.cpp
index f23d832953..7f4b6057ce 100644
--- a/src/qml/jsruntime/qv4sequenceobject.cpp
+++ b/src/qml/jsruntime/qv4sequenceobject.cpp
@@ -547,7 +547,7 @@ ReturnedValue SequencePrototype::method_sort(const FunctionObject *b, const Valu
{
Scope scope(b);
QV4::ScopedObject o(scope, thisObject);
- if (!o || !o->isListType())
+ if (!o || !o->isV4SequenceType())
THROW_TYPE_ERROR();
if (argc >= 2)
@@ -610,7 +610,7 @@ ReturnedValue SequencePrototype::fromData(ExecutionEngine *engine, QMetaType typ
QVariant SequencePrototype::toVariant(const Sequence *object)
{
- Q_ASSERT(object->isListType());
+ Q_ASSERT(object->isV4SequenceType());
return object->toVariant();
}