diff options
Diffstat (limited to 'src/qml/jsruntime')
-rw-r--r-- | src/qml/jsruntime/qv4arraydata.cpp | 73 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4arraydata_p.h | 68 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4arrayiterator.cpp | 1 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4arrayobject.cpp | 39 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4engine.cpp | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4managed.cpp | 3 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4managed_p.h | 9 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4scopedvalue_p.h | 7 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4sequenceobject.cpp | 4 |
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(); } |