[SCM] WebKit Debian packaging branch, debian/experimental, updated. upstream/1.3.3-9427-gc2be6fc

commit-queue at webkit.org commit-queue at webkit.org
Wed Dec 22 11:08:49 UTC 2010


The following commit has been merged in the debian/experimental branch:
commit 07fa9ad75106a14b7d8481f37fd8c22376896b2b
Author: commit-queue at webkit.org <commit-queue at webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Tue Jul 13 19:33:57 2010 +0000

    2010-07-13  Jedrzej Nowacki  <jedrzej.nowacki at nokia.com>
    
            Reviewed by Simon Hausmann.
    
            Introduce QScriptValueIterator.
    
            The QScriptValueIterator class permits to iterate over a QScriptValue's properties.
    
            [Qt] QtScript should provide an API for enumerating a JS object's properties
            https://bugs.webkit.org/show_bug.cgi?id=41680
    
            * api/QtScript.pro:
            * api/qscriptvalueiterator.cpp: Added.
            (QScriptValueIterator::QScriptValueIterator):
            (QScriptValueIterator::~QScriptValueIterator):
            (QScriptValueIterator::hasNext):
            (QScriptValueIterator::next):
            (QScriptValueIterator::hasPrevious):
            (QScriptValueIterator::previous):
            (QScriptValueIterator::toFront):
            (QScriptValueIterator::toBack):
            (QScriptValueIterator::name):
            (QScriptValueIterator::scriptName):
            (QScriptValueIterator::value):
            (QScriptValueIterator::setValue):
            (QScriptValueIterator::remove):
            (QScriptValueIterator::flags):
            (QScriptValueIterator::operator=):
            * api/qscriptvalueiterator.h: Added.
            * api/qscriptvalueiterator_p.h: Added.
            (QScriptValueIteratorPrivate::QScriptValueIteratorPrivate):
            (QScriptValueIteratorPrivate::~QScriptValueIteratorPrivate):
            (QScriptValueIteratorPrivate::hasNext):
            (QScriptValueIteratorPrivate::next):
            (QScriptValueIteratorPrivate::hasPrevious):
            (QScriptValueIteratorPrivate::previous):
            (QScriptValueIteratorPrivate::name):
            (QScriptValueIteratorPrivate::scriptName):
            (QScriptValueIteratorPrivate::value):
            (QScriptValueIteratorPrivate::setValue):
            (QScriptValueIteratorPrivate::remove):
            (QScriptValueIteratorPrivate::toFront):
            (QScriptValueIteratorPrivate::toBack):
            (QScriptValueIteratorPrivate::flags):
            (QScriptValueIteratorPrivate::isValid):
            (QScriptValueIteratorPrivate::engine):
            * tests/qscriptvalueiterator/qscriptvalueiterator.pro: Added.
            * tests/qscriptvalueiterator/tst_qscriptvalueiterator.cpp: Added.
            (tst_QScriptValueIterator::tst_QScriptValueIterator):
            (tst_QScriptValueIterator::~tst_QScriptValueIterator):
            (tst_QScriptValueIterator::iterateForward_data):
            (tst_QScriptValueIterator::iterateForward):
            (tst_QScriptValueIterator::iterateBackward_data):
            (tst_QScriptValueIterator::iterateBackward):
            (tst_QScriptValueIterator::iterateArray_data):
            (tst_QScriptValueIterator::iterateArray):
            (tst_QScriptValueIterator::iterateBackAndForth):
            (tst_QScriptValueIterator::setValue):
            (tst_QScriptValueIterator::remove):
            (tst_QScriptValueIterator::removeMixed):
            (tst_QScriptValueIterator::removeUndeletable):
            (tst_QScriptValueIterator::iterateString):
            (tst_QScriptValueIterator::assignObjectToIterator):
            * tests/tests.pro:
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@63233 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/JavaScriptCore/qt/ChangeLog b/JavaScriptCore/qt/ChangeLog
index 71b4a21..2599aed 100644
--- a/JavaScriptCore/qt/ChangeLog
+++ b/JavaScriptCore/qt/ChangeLog
@@ -1,3 +1,68 @@
+2010-07-13  Jedrzej Nowacki  <jedrzej.nowacki at nokia.com>
+
+        Reviewed by Simon Hausmann.
+
+        Introduce QScriptValueIterator.
+
+        The QScriptValueIterator class permits to iterate over a QScriptValue's properties.
+
+        [Qt] QtScript should provide an API for enumerating a JS object's properties
+        https://bugs.webkit.org/show_bug.cgi?id=41680
+
+        * api/QtScript.pro:
+        * api/qscriptvalueiterator.cpp: Added.
+        (QScriptValueIterator::QScriptValueIterator):
+        (QScriptValueIterator::~QScriptValueIterator):
+        (QScriptValueIterator::hasNext):
+        (QScriptValueIterator::next):
+        (QScriptValueIterator::hasPrevious):
+        (QScriptValueIterator::previous):
+        (QScriptValueIterator::toFront):
+        (QScriptValueIterator::toBack):
+        (QScriptValueIterator::name):
+        (QScriptValueIterator::scriptName):
+        (QScriptValueIterator::value):
+        (QScriptValueIterator::setValue):
+        (QScriptValueIterator::remove):
+        (QScriptValueIterator::flags):
+        (QScriptValueIterator::operator=):
+        * api/qscriptvalueiterator.h: Added.
+        * api/qscriptvalueiterator_p.h: Added.
+        (QScriptValueIteratorPrivate::QScriptValueIteratorPrivate):
+        (QScriptValueIteratorPrivate::~QScriptValueIteratorPrivate):
+        (QScriptValueIteratorPrivate::hasNext):
+        (QScriptValueIteratorPrivate::next):
+        (QScriptValueIteratorPrivate::hasPrevious):
+        (QScriptValueIteratorPrivate::previous):
+        (QScriptValueIteratorPrivate::name):
+        (QScriptValueIteratorPrivate::scriptName):
+        (QScriptValueIteratorPrivate::value):
+        (QScriptValueIteratorPrivate::setValue):
+        (QScriptValueIteratorPrivate::remove):
+        (QScriptValueIteratorPrivate::toFront):
+        (QScriptValueIteratorPrivate::toBack):
+        (QScriptValueIteratorPrivate::flags):
+        (QScriptValueIteratorPrivate::isValid):
+        (QScriptValueIteratorPrivate::engine):
+        * tests/qscriptvalueiterator/qscriptvalueiterator.pro: Added.
+        * tests/qscriptvalueiterator/tst_qscriptvalueiterator.cpp: Added.
+        (tst_QScriptValueIterator::tst_QScriptValueIterator):
+        (tst_QScriptValueIterator::~tst_QScriptValueIterator):
+        (tst_QScriptValueIterator::iterateForward_data):
+        (tst_QScriptValueIterator::iterateForward):
+        (tst_QScriptValueIterator::iterateBackward_data):
+        (tst_QScriptValueIterator::iterateBackward):
+        (tst_QScriptValueIterator::iterateArray_data):
+        (tst_QScriptValueIterator::iterateArray):
+        (tst_QScriptValueIterator::iterateBackAndForth):
+        (tst_QScriptValueIterator::setValue):
+        (tst_QScriptValueIterator::remove):
+        (tst_QScriptValueIterator::removeMixed):
+        (tst_QScriptValueIterator::removeUndeletable):
+        (tst_QScriptValueIterator::iterateString):
+        (tst_QScriptValueIterator::assignObjectToIterator):
+        * tests/tests.pro:
+
 2010-07-09  Jedrzej Nowacki  <jedrzej.nowacki at nokia.com>
 
         Reviewed by Simon Hausmann.
diff --git a/JavaScriptCore/qt/api/QtScript.pro b/JavaScriptCore/qt/api/QtScript.pro
index 3c2691e..fb49cfe 100644
--- a/JavaScriptCore/qt/api/QtScript.pro
+++ b/JavaScriptCore/qt/api/QtScript.pro
@@ -24,6 +24,7 @@ INCLUDEPATH += $$PWD/../../API
 SOURCES +=  $$PWD/qscriptengine.cpp \
             $$PWD/qscriptengine_p.cpp \
             $$PWD/qscriptvalue.cpp \
+            $$PWD/qscriptvalueiterator.cpp \
             $$PWD/qscriptstring.cpp \
             $$PWD/qscriptprogram.cpp \
             $$PWD/qscriptsyntaxcheckresult.cpp \
@@ -33,6 +34,8 @@ HEADERS +=  $$PWD/qtscriptglobal.h \
             $$PWD/qscriptengine_p.h \
             $$PWD/qscriptvalue.h \
             $$PWD/qscriptvalue_p.h \
+            $$PWD/qscriptvalueiterator.h \
+            $$PWD/qscriptvalueiterator_p.h \
             $$PWD/qscriptconverter_p.h \
             $$PWD/qscriptstring.h \
             $$PWD/qscriptstring_p.h \
diff --git a/JavaScriptCore/qt/api/qscriptvalueiterator.cpp b/JavaScriptCore/qt/api/qscriptvalueiterator.cpp
new file mode 100644
index 0000000..f1caa61
--- /dev/null
+++ b/JavaScriptCore/qt/api/qscriptvalueiterator.cpp
@@ -0,0 +1,226 @@
+/*
+    Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+*/
+
+#include "config.h"
+
+#include "qscriptvalueiterator.h"
+
+#include "qscriptvalue_p.h"
+#include "qscriptvalueiterator_p.h"
+
+/*!
+    \class QScriptValueIterator
+
+    \brief The QScriptValueIterator class provides a Java-style iterator for QScriptValue.
+
+    \ingroup script
+
+
+    The QScriptValueIterator constructor takes a QScriptValue as
+    argument.  After construction, the iterator is located at the very
+    beginning of the sequence of properties. Here's how to iterate over
+    all the properties of a QScriptValue:
+
+    \snippet doc/src/snippets/code/src_script_qscriptvalueiterator.cpp 0
+
+    The next() advances the iterator. The name(), value() and flags()
+    functions return the name, value and flags of the last item that was
+    jumped over.
+
+    If you want to remove properties as you iterate over the
+    QScriptValue, use remove(). If you want to modify the value of a
+    property, use setValue().
+
+    Note that QScriptValueIterator only iterates over the QScriptValue's
+    own properties; i.e. it does not follow the prototype chain. You can
+    use a loop like this to follow the prototype chain:
+
+    \snippet doc/src/snippets/code/src_script_qscriptvalueiterator.cpp 1
+
+    Note that QScriptValueIterator will not automatically skip over
+    properties that have the QScriptValue::SkipInEnumeration flag set;
+    that flag only affects iteration in script code.  If you want, you
+    can skip over such properties with code like the following:
+
+    \snippet doc/src/snippets/code/src_script_qscriptvalueiterator.cpp 2
+
+    \sa QScriptValue::property()
+*/
+
+/*!
+    Constructs an iterator for traversing \a object. The iterator is
+    set to be at the front of the sequence of properties (before the
+    first property).
+*/
+QScriptValueIterator::QScriptValueIterator(const QScriptValue& object)
+    : d_ptr(new QScriptValueIteratorPrivate(QScriptValuePrivate::get(object)))
+{}
+
+/*!
+    Destroys the iterator.
+*/
+QScriptValueIterator::~QScriptValueIterator()
+{}
+
+/*!
+    Returns true if there is at least one item ahead of the iterator
+    (i.e. the iterator is \e not at the back of the property sequence);
+    otherwise returns false.
+
+    \sa next(), hasPrevious()
+*/
+bool QScriptValueIterator::hasNext() const
+{
+    return d_ptr->hasNext();
+}
+
+/*!
+    Advances the iterator by one position.
+
+    Calling this function on an iterator located at the back of the
+    container leads to undefined results.
+
+    \sa hasNext(), previous(), name()
+*/
+void QScriptValueIterator::next()
+{
+    d_ptr->next();
+}
+
+/*!
+    Returns true if there is at least one item behind the iterator
+    (i.e. the iterator is \e not at the front of the property sequence);
+    otherwise returns false.
+
+    \sa previous(), hasNext()
+*/
+bool QScriptValueIterator::hasPrevious() const
+{
+    return d_ptr->hasPrevious();
+}
+
+/*!
+    Moves the iterator back by one position.
+
+    Calling this function on an iterator located at the front of the
+    container leads to undefined results.
+
+    \sa hasPrevious(), next(), name()
+*/
+void QScriptValueIterator::previous()
+{
+    d_ptr->previous();
+}
+
+/*!
+    Moves the iterator to the front of the QScriptValue (before the
+    first property).
+
+    \sa toBack(), next()
+*/
+void QScriptValueIterator::toFront()
+{
+    d_ptr->toFront();
+}
+
+/*!
+    Moves the iterator to the back of the QScriptValue (after the
+    last property).
+
+    \sa toFront(), previous()
+*/
+void QScriptValueIterator::toBack()
+{
+    d_ptr->toBack();
+}
+
+/*!
+    Returns the name of the last property that was jumped over using
+    next() or previous().
+
+    \sa value(), flags()
+*/
+QString QScriptValueIterator::name() const
+{
+    return d_ptr->name();
+}
+
+/*!
+    Returns the name of the last property that was jumped over using
+    next() or previous().
+*/
+QScriptString QScriptValueIterator::scriptName() const
+{
+    return QScriptStringPrivate::get(d_ptr->scriptName());
+}
+
+/*!
+    Returns the value of the last property that was jumped over using
+    next() or previous().
+
+    \sa setValue(), name()
+*/
+QScriptValue QScriptValueIterator::value() const
+{
+    return QScriptValuePrivate::get(d_ptr->value());
+}
+
+/*!
+    Sets the \a value of the last property that was jumped over using
+    next() or previous().
+
+    \sa value(), name()
+*/
+void QScriptValueIterator::setValue(const QScriptValue& value)
+{
+    d_ptr->setValue(QScriptValuePrivate::get(value));
+}
+
+/*!
+    Removes the last property that was jumped over using next()
+    or previous().
+
+    \sa setValue()
+*/
+void QScriptValueIterator::remove()
+{
+    d_ptr->remove();
+}
+
+/*!
+    Returns the flags of the last property that was jumped over using
+    next() or previous().
+
+    \sa value()
+*/
+QScriptValue::PropertyFlags QScriptValueIterator::flags() const
+{
+    return d_ptr->flags();
+}
+
+/*!
+    Makes the iterator operate on \a object. The iterator is set to be
+    at the front of the sequence of properties (before the first
+    property).
+*/
+QScriptValueIterator& QScriptValueIterator::operator=(QScriptValue& object)
+{
+    d_ptr = new QScriptValueIteratorPrivate(QScriptValuePrivate::get(object));
+    return *this;
+}
diff --git a/JavaScriptCore/qt/api/qscriptvalueiterator.h b/JavaScriptCore/qt/api/qscriptvalueiterator.h
new file mode 100644
index 0000000..0c90661
--- /dev/null
+++ b/JavaScriptCore/qt/api/qscriptvalueiterator.h
@@ -0,0 +1,63 @@
+/*
+    Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+*/
+
+#ifndef qscriptvalueiterator_h
+#define qscriptvalueiterator_h
+
+#include "qtscriptglobal.h"
+#include "qscriptstring.h"
+#include <QtCore/qshareddata.h>
+#include "qscriptvalue.h"
+
+class QScriptValue;
+class QScriptValueIteratorPrivate;
+
+
+class Q_JAVASCRIPT_EXPORT QScriptValueIterator {
+public:
+    QScriptValueIterator(const QScriptValue& value);
+    ~QScriptValueIterator();
+
+    bool hasNext() const;
+    void next();
+
+    bool hasPrevious() const;
+    void previous();
+
+    QString name() const;
+    QScriptString scriptName() const;
+
+    QScriptValue value() const;
+    void setValue(const QScriptValue& value);
+
+    void remove();
+    QScriptValue::PropertyFlags flags() const;
+
+    void toFront();
+    void toBack();
+
+    QScriptValueIterator& operator=(QScriptValue& value);
+private:
+    QExplicitlySharedDataPointer<QScriptValueIteratorPrivate> d_ptr;
+
+    Q_DECLARE_PRIVATE(QScriptValueIterator)
+    Q_DISABLE_COPY(QScriptValueIterator)
+};
+
+#endif // qscriptvalueiterator_h
diff --git a/JavaScriptCore/qt/api/qscriptvalueiterator_p.h b/JavaScriptCore/qt/api/qscriptvalueiterator_p.h
new file mode 100644
index 0000000..66fc001
--- /dev/null
+++ b/JavaScriptCore/qt/api/qscriptvalueiterator_p.h
@@ -0,0 +1,206 @@
+/*
+    Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+*/
+
+#ifndef qscriptvalueiterator_p_h
+#define qscriptvalueiterator_p_h
+
+#include "qscriptvalue_p.h"
+#include <JavaScriptCore/JavaScript.h>
+#include <JavaScriptCore/JSRetainPtr.h>
+#include <QtCore/qshareddata.h>
+#include <QtCore/qvector.h>
+
+class QScriptValueIteratorPrivate: public QSharedData {
+public:
+    inline QScriptValueIteratorPrivate(const QScriptValuePrivate* value);
+    inline ~QScriptValueIteratorPrivate();
+
+    inline bool hasNext();
+    inline void next();
+
+    inline bool hasPrevious();
+    inline void previous();
+
+    inline QString name() const;
+    inline QScriptStringPrivate* scriptName() const;
+
+    inline QScriptValuePrivate* value() const;
+    inline void setValue(const QScriptValuePrivate* value);
+
+    inline void remove();
+
+    inline void toFront();
+    inline void toBack();
+
+    QScriptValue::PropertyFlags flags() const;
+
+    inline bool isValid() const;
+private:
+    inline QScriptEnginePrivate* engine() const;
+
+    QExplicitlySharedDataPointer<QScriptValuePrivate> m_object;
+    QVector<JSStringRef> m_names;
+    QMutableVectorIterator<JSStringRef> m_idx;
+};
+
+inline QScriptValueIteratorPrivate::QScriptValueIteratorPrivate(const QScriptValuePrivate* value)
+    : m_object(const_cast<QScriptValuePrivate*>(value))
+    , m_idx(m_names)
+{
+    // FIXME There is assumption that global object wasn't changed (bug 41839).
+    // FIXME We can't use C API function JSObjectGetPropertyNames as it returns only enumerable properties.
+    if (const_cast<QScriptValuePrivate*>(value)->isObject()) {
+        static JSStringRef objectName = QScriptConverter::toString("Object");
+        static JSStringRef getOwnPropertyNamesName = QScriptConverter::toString("getOwnPropertyNames");
+
+        JSValueRef exception = 0;
+        JSObjectRef globalObject = JSContextGetGlobalObject(*engine());
+        Q_ASSERT(JSValueIsObject(*engine(), globalObject));
+        JSValueRef objectConstructor = JSObjectGetProperty(*engine(), globalObject, objectName, &exception);
+        Q_ASSERT(JSValueIsObject(*engine(), objectConstructor));
+        Q_ASSERT(!exception);
+        JSValueRef propertyNamesGetter = JSObjectGetProperty(*engine(), const_cast<JSObjectRef>(objectConstructor), getOwnPropertyNamesName, &exception);
+        Q_ASSERT(JSValueIsObject(*engine(), propertyNamesGetter));
+        Q_ASSERT(!exception);
+
+        JSValueRef arguments[] = { *m_object };
+        JSObjectRef propertyNames
+                = const_cast<JSObjectRef>(JSObjectCallAsFunction(*engine(),
+                                                                const_cast<JSObjectRef>(propertyNamesGetter),
+                                                                /* thisObject */ 0,
+                                                                /* argumentCount */ 1,
+                                                                arguments,
+                                                                &exception));
+        Q_ASSERT(JSValueIsObject(*engine(), propertyNames));
+        Q_ASSERT(!exception);
+        static JSStringRef lengthName = QScriptConverter::toString("length");
+        int count = JSValueToNumber(*engine(), JSObjectGetProperty(*engine(), propertyNames, lengthName, &exception), &exception);
+
+        Q_ASSERT(!exception);
+        m_names.reserve(count);
+        for (int i = 0; i < count; ++i) {
+            JSValueRef tmp = JSObjectGetPropertyAtIndex(*engine(), propertyNames, i, &exception);
+            m_names.append(JSValueToStringCopy(*engine(), tmp, &exception));
+            Q_ASSERT(!exception);
+        }
+        m_idx = m_names;
+    } else
+        m_object = 0;
+}
+
+inline QScriptValueIteratorPrivate::~QScriptValueIteratorPrivate()
+{
+    QVector<JSStringRef>::const_iterator i = m_names.constBegin();
+    for (; i != m_names.constEnd(); ++i)
+        JSStringRelease(*i);
+}
+
+inline bool QScriptValueIteratorPrivate::hasNext()
+{
+    return m_idx.hasNext();
+}
+
+inline void QScriptValueIteratorPrivate::next()
+{
+    // FIXME (Qt5) This method should return a value (QTBUG-11226).
+    m_idx.next();
+}
+
+inline bool QScriptValueIteratorPrivate::hasPrevious()
+{
+    return m_idx.hasPrevious();
+}
+
+inline void QScriptValueIteratorPrivate::previous()
+{
+    m_idx.previous();
+}
+
+inline QString QScriptValueIteratorPrivate::name() const
+{
+    if (!isValid())
+        return QString();
+    return QScriptConverter::toString(m_idx.value());
+}
+
+inline QScriptStringPrivate* QScriptValueIteratorPrivate::scriptName() const
+{
+    if (!isValid())
+        return new QScriptStringPrivate();
+    return new QScriptStringPrivate(QScriptConverter::toString(m_idx.value()));
+}
+
+inline QScriptValuePrivate* QScriptValueIteratorPrivate::value() const
+{
+    if (!isValid())
+        return new QScriptValuePrivate();
+    JSValueRef exception = 0;
+    JSValueRef value = m_object->property(m_idx.value(), &exception);
+    engine()->setException(exception);
+    return new QScriptValuePrivate(engine(), value);
+}
+
+inline void QScriptValueIteratorPrivate::setValue(const QScriptValuePrivate* value)
+{
+    if (!isValid())
+        return;
+    JSValueRef exception = 0;
+    m_object->setProperty(m_idx.value(), *value, /* flags */ 0, &exception);
+    engine()->setException(exception);
+}
+
+inline void QScriptValueIteratorPrivate::remove()
+{
+    if (!isValid())
+        return;
+    JSValueRef exception = 0;
+    m_object->deleteProperty(m_idx.value(), &exception);
+    engine()->setException(exception);
+    m_idx.remove();
+}
+
+inline void QScriptValueIteratorPrivate::toFront()
+{
+    m_idx.toFront();
+}
+
+inline void QScriptValueIteratorPrivate::toBack()
+{
+    m_idx.toBack();
+}
+
+QScriptValue::PropertyFlags QScriptValueIteratorPrivate::flags() const
+{
+    if (!isValid())
+        return QScriptValue::PropertyFlags(0);
+    return m_object->propertyFlags(m_idx.value(), QScriptValue::ResolveLocal);
+}
+
+inline bool QScriptValueIteratorPrivate::isValid() const
+{
+    return m_object;
+}
+
+inline QScriptEnginePrivate* QScriptValueIteratorPrivate::engine() const
+{
+    Q_ASSERT(isValid());
+    return m_object->engine();
+}
+
+#endif // qscriptvalueiterator_p_h
diff --git a/JavaScriptCore/qt/tests/qscriptvalueiterator/qscriptvalueiterator.pro b/JavaScriptCore/qt/tests/qscriptvalueiterator/qscriptvalueiterator.pro
new file mode 100644
index 0000000..5314ec9
--- /dev/null
+++ b/JavaScriptCore/qt/tests/qscriptvalueiterator/qscriptvalueiterator.pro
@@ -0,0 +1,7 @@
+TEMPLATE = app
+TARGET = tst_qscriptvalueiterator
+QT += testlib
+include(../tests.pri)
+
+SOURCES += tst_qscriptvalueiterator.cpp
+
diff --git a/JavaScriptCore/qt/tests/qscriptvalueiterator/tst_qscriptvalueiterator.cpp b/JavaScriptCore/qt/tests/qscriptvalueiterator/tst_qscriptvalueiterator.cpp
new file mode 100644
index 0000000..43d0042
--- /dev/null
+++ b/JavaScriptCore/qt/tests/qscriptvalueiterator/tst_qscriptvalueiterator.cpp
@@ -0,0 +1,531 @@
+/*
+    Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+*/
+
+#ifndef tst_qscriptvalueiterator_h
+#define tst_qscriptvalueiterator_h
+
+#include "qscriptengine.h"
+#include "qscriptvalue.h"
+#include "qscriptvalueiterator.h"
+#include <QtCore/qhash.h>
+#include <QtTest/QtTest>
+
+class tst_QScriptValueIterator : public QObject {
+    Q_OBJECT
+
+public:
+    tst_QScriptValueIterator();
+    virtual ~tst_QScriptValueIterator();
+
+private slots:
+    void iterateForward_data();
+    void iterateForward();
+    void iterateBackward_data();
+    void iterateBackward();
+    void iterateArray_data();
+    void iterateArray();
+    void iterateBackAndForth();
+    void setValue();
+    void remove();
+    void removeMixed();
+    void removeUndeletable();
+    void iterateString();
+    void assignObjectToIterator();
+};
+
+tst_QScriptValueIterator::tst_QScriptValueIterator()
+{
+}
+
+tst_QScriptValueIterator::~tst_QScriptValueIterator()
+{
+}
+
+void tst_QScriptValueIterator::iterateForward_data()
+{
+    QTest::addColumn<QStringList>("propertyNames");
+    QTest::addColumn<QStringList>("propertyValues");
+
+    QTest::newRow("no properties")
+        << QStringList() << QStringList();
+    QTest::newRow("foo=bar")
+        << (QStringList() << "foo")
+        << (QStringList() << "bar");
+    QTest::newRow("foo=bar, baz=123")
+        << (QStringList() << "foo" << "baz")
+        << (QStringList() << "bar" << "123");
+    QTest::newRow("foo=bar, baz=123, rab=oof")
+        << (QStringList() << "foo" << "baz" << "rab")
+        << (QStringList() << "bar" << "123" << "oof");
+}
+
+void tst_QScriptValueIterator::iterateForward()
+{
+    QFETCH(QStringList, propertyNames);
+    QFETCH(QStringList, propertyValues);
+    QMap<QString, QString> pmap;
+    Q_ASSERT(propertyNames.size() == propertyValues.size());
+
+    QScriptEngine engine;
+    QScriptValue object = engine.newObject();
+    for (int i = 0; i < propertyNames.size(); ++i) {
+        QString name = propertyNames.at(i);
+        QString value = propertyValues.at(i);
+        pmap.insert(name, value);
+        object.setProperty(name, QScriptValue(&engine, value));
+    }
+    QScriptValue otherObject = engine.newObject();
+    otherObject.setProperty("foo", QScriptValue(&engine, 123456));
+    otherObject.setProperty("protoProperty", QScriptValue(&engine, 654321));
+    object.setPrototype(otherObject); // should not affect iterator
+
+    QStringList lst;
+    QScriptValueIterator it(object);
+    while (!pmap.isEmpty()) {
+        QCOMPARE(it.hasNext(), true);
+        QCOMPARE(it.hasNext(), true);
+        it.next();
+        QString name = it.name();
+        QCOMPARE(pmap.contains(name), true);
+        QCOMPARE(it.name(), name);
+        QCOMPARE(it.flags(), object.propertyFlags(name));
+        QCOMPARE(it.value().strictlyEquals(QScriptValue(&engine, pmap.value(name))), true);
+        QCOMPARE(it.scriptName(), engine.toStringHandle(name));
+        pmap.remove(name);
+        lst.append(name);
+    }
+
+    QCOMPARE(it.hasNext(), false);
+    QCOMPARE(it.hasNext(), false);
+
+    it.toFront();
+    for (int i = 0; i < lst.count(); ++i) {
+        QCOMPARE(it.hasNext(), true);
+        it.next();
+        QCOMPARE(it.name(), lst.at(i));
+    }
+
+    for (int i = 0; i < lst.count(); ++i) {
+        QCOMPARE(it.hasPrevious(), true);
+        it.previous();
+        QCOMPARE(it.name(), lst.at(lst.count()-1-i));
+    }
+    QCOMPARE(it.hasPrevious(), false);
+}
+
+void tst_QScriptValueIterator::iterateBackward_data()
+{
+    iterateForward_data();
+}
+
+void tst_QScriptValueIterator::iterateBackward()
+{
+    QFETCH(QStringList, propertyNames);
+    QFETCH(QStringList, propertyValues);
+    QMap<QString, QString> pmap;
+    Q_ASSERT(propertyNames.size() == propertyValues.size());
+
+    QScriptEngine engine;
+    QScriptValue object = engine.newObject();
+    for (int i = 0; i < propertyNames.size(); ++i) {
+        QString name = propertyNames.at(i);
+        QString value = propertyValues.at(i);
+        pmap.insert(name, value);
+        object.setProperty(name, QScriptValue(&engine, value));
+    }
+
+    QStringList lst;
+    QScriptValueIterator it(object);
+    it.toBack();
+    while (!pmap.isEmpty()) {
+        QCOMPARE(it.hasPrevious(), true);
+        QCOMPARE(it.hasPrevious(), true);
+        it.previous();
+        QString name = it.name();
+        QCOMPARE(pmap.contains(name), true);
+        QCOMPARE(it.name(), name);
+        QCOMPARE(it.flags(), object.propertyFlags(name));
+        QCOMPARE(it.value().strictlyEquals(QScriptValue(&engine, pmap.value(name))), true);
+        pmap.remove(name);
+        lst.append(name);
+    }
+
+    QCOMPARE(it.hasPrevious(), false);
+    QCOMPARE(it.hasPrevious(), false);
+
+    it.toBack();
+    for (int i = 0; i < lst.count(); ++i) {
+        QCOMPARE(it.hasPrevious(), true);
+        it.previous();
+        QCOMPARE(it.name(), lst.at(i));
+    }
+
+    for (int i = 0; i < lst.count(); ++i) {
+        QCOMPARE(it.hasNext(), true);
+        it.next();
+        QCOMPARE(it.name(), lst.at(lst.count()-1-i));
+    }
+    QCOMPARE(it.hasNext(), false);
+}
+
+void tst_QScriptValueIterator::iterateArray_data()
+{
+    QTest::addColumn<QStringList>("inputPropertyNames");
+    QTest::addColumn<QStringList>("inputPropertyValues");
+    QTest::addColumn<QStringList>("propertyNames");
+    QTest::addColumn<QStringList>("propertyValues");
+    QTest::newRow("no elements") << QStringList() << QStringList() << QStringList() << QStringList();
+
+    QTest::newRow("0=foo, 1=barr")
+        << (QStringList() << "0" << "1")
+        << (QStringList() << "foo" << "bar")
+        << (QStringList() << "0" << "1")
+        << (QStringList() << "foo" << "bar");
+
+    QTest::newRow("0=foo, 3=barr")
+        << (QStringList() << "0" << "1" << "2" << "3")
+        << (QStringList() << "foo" << "" << "" << "bar")
+        << (QStringList() << "0" << "1" << "2" << "3")
+        << (QStringList() << "foo" << "" << "" << "bar");
+}
+
+void tst_QScriptValueIterator::iterateArray()
+{
+    QFETCH(QStringList, inputPropertyNames);
+    QFETCH(QStringList, inputPropertyValues);
+    QFETCH(QStringList, propertyNames);
+    QFETCH(QStringList, propertyValues);
+
+    QScriptEngine engine;
+    QScriptValue array = engine.newArray();
+    for (int i = 0; i < inputPropertyNames.size(); ++i)
+        array.setProperty(inputPropertyNames.at(i), inputPropertyValues.at(i));
+
+    int length = array.property("length").toInt32();
+    QCOMPARE(length, propertyNames.size());
+    QScriptValueIterator it(array);
+    for (int i = 0; i < length; ++i) {
+        QCOMPARE(it.hasNext(), true);
+        it.next();
+        QCOMPARE(it.name(), propertyNames.at(i));
+        QCOMPARE(it.flags(), array.propertyFlags(propertyNames.at(i)));
+        QVERIFY(it.value().strictlyEquals(array.property(propertyNames.at(i))));
+        QCOMPARE(it.value().toString(), propertyValues.at(i));
+    }
+    QVERIFY(it.hasNext());
+    it.next();
+    QCOMPARE(it.name(), QString::fromLatin1("length"));
+    QVERIFY(it.value().isNumber());
+    QCOMPARE(it.value().toInt32(), length);
+    QCOMPARE(it.flags(), QScriptValue::PropertyFlags(QScriptValue::SkipInEnumeration | QScriptValue::Undeletable));
+
+    it.previous();
+    QCOMPARE(it.hasPrevious(), length > 0);
+    for (int i = length - 1; i >= 0; --i) {
+        it.previous();
+        QCOMPARE(it.name(), propertyNames.at(i));
+        QCOMPARE(it.flags(), array.propertyFlags(propertyNames.at(i)));
+        QVERIFY(it.value().strictlyEquals(array.property(propertyNames.at(i))));
+        QCOMPARE(it.value().toString(), propertyValues.at(i));
+        QCOMPARE(it.hasPrevious(), i > 0);
+    }
+    QCOMPARE(it.hasPrevious(), false);
+
+    // hasNext() and hasPrevious() cache their result; verify that the result is in sync
+    if (length > 1) {
+        QVERIFY(it.hasNext());
+        it.next();
+        QCOMPARE(it.name(), QString::fromLatin1("0"));
+        QVERIFY(it.hasNext());
+        it.previous();
+        QCOMPARE(it.name(), QString::fromLatin1("0"));
+        QVERIFY(!it.hasPrevious());
+        it.next();
+        QCOMPARE(it.name(), QString::fromLatin1("0"));
+        QVERIFY(it.hasPrevious());
+        it.next();
+        QCOMPARE(it.name(), QString::fromLatin1("1"));
+    }
+    {
+        // same test as object:
+        QScriptValue originalArray = engine.newArray();
+        for (int i = 0; i < inputPropertyNames.size(); ++i)
+            originalArray.setProperty(inputPropertyNames.at(i), inputPropertyValues.at(i));
+
+        QScriptValue array = originalArray.toObject();
+        int length = array.property("length").toInt32();
+        QCOMPARE(length, propertyNames.size());
+        QScriptValueIterator it(array);
+        for (int i = 0; i < length; ++i) {
+            QCOMPARE(it.hasNext(), true);
+            it.next();
+            QCOMPARE(it.name(), propertyNames.at(i));
+            QCOMPARE(it.flags(), array.propertyFlags(propertyNames.at(i)));
+            QVERIFY(it.value().strictlyEquals(array.property(propertyNames.at(i))));
+            QCOMPARE(it.value().toString(), propertyValues.at(i));
+        }
+        QCOMPARE(it.hasNext(), true);
+        it.next();
+        QCOMPARE(it.name(), QString::fromLatin1("length"));
+    }
+}
+
+void tst_QScriptValueIterator::iterateBackAndForth()
+{
+    QScriptEngine engine;
+    {
+        QScriptValue object = engine.newObject();
+        object.setProperty("foo", QScriptValue(&engine, "bar"));
+        object.setProperty("rab", QScriptValue(&engine, "oof"),
+                           QScriptValue::SkipInEnumeration); // should not affect iterator
+        QScriptValueIterator it(object);
+        QVERIFY(it.hasNext());
+        it.next();
+        QCOMPARE(it.name(), QLatin1String("foo"));
+        QVERIFY(it.hasPrevious());
+        it.previous();
+        QCOMPARE(it.name(), QLatin1String("foo"));
+        QVERIFY(it.hasNext());
+        it.next();
+        QCOMPARE(it.name(), QLatin1String("foo"));
+        QVERIFY(it.hasPrevious());
+        it.previous();
+        QCOMPARE(it.name(), QLatin1String("foo"));
+        QVERIFY(it.hasNext());
+        it.next();
+        QCOMPARE(it.name(), QLatin1String("foo"));
+        QVERIFY(it.hasNext());
+        it.next();
+        QCOMPARE(it.name(), QLatin1String("rab"));
+        QVERIFY(it.hasPrevious());
+        it.previous();
+        QCOMPARE(it.name(), QLatin1String("rab"));
+        QVERIFY(it.hasNext());
+        it.next();
+        QCOMPARE(it.name(), QLatin1String("rab"));
+        QVERIFY(it.hasPrevious());
+        it.previous();
+        QCOMPARE(it.name(), QLatin1String("rab"));
+    }
+    {
+        // hasNext() and hasPrevious() cache their result; verify that the result is in sync
+        QScriptValue object = engine.newObject();
+        object.setProperty("foo", QScriptValue(&engine, "bar"));
+        object.setProperty("rab", QScriptValue(&engine, "oof"));
+        QScriptValueIterator it(object);
+        QVERIFY(it.hasNext());
+        it.next();
+        QCOMPARE(it.name(), QString::fromLatin1("foo"));
+        QVERIFY(it.hasNext());
+        it.previous();
+        QCOMPARE(it.name(), QString::fromLatin1("foo"));
+        QVERIFY(!it.hasPrevious());
+        it.next();
+        QCOMPARE(it.name(), QString::fromLatin1("foo"));
+        QVERIFY(it.hasPrevious());
+        it.next();
+        QCOMPARE(it.name(), QString::fromLatin1("rab"));
+    }
+}
+
+void tst_QScriptValueIterator::setValue()
+{
+    QScriptEngine engine;
+    QScriptValue object = engine.newObject();
+    object.setProperty("foo", QScriptValue(&engine, "bar"));
+    QScriptValueIterator it(object);
+    it.next();
+    QCOMPARE(it.name(), QLatin1String("foo"));
+    it.setValue(QScriptValue(&engine, "baz"));
+    QCOMPARE(it.value().strictlyEquals(QScriptValue(&engine, QLatin1String("baz"))), true);
+    QCOMPARE(object.property("foo").toString(), QLatin1String("baz"));
+    it.setValue(QScriptValue(&engine, "zab"));
+    QCOMPARE(it.value().strictlyEquals(QScriptValue(&engine, QLatin1String("zab"))), true);
+    QCOMPARE(object.property("foo").toString(), QLatin1String("zab"));
+}
+
+void tst_QScriptValueIterator::remove()
+{
+    QScriptEngine engine;
+    QScriptValue object = engine.newObject();
+    object.setProperty("foo", QScriptValue(&engine, "bar"),
+                       QScriptValue::SkipInEnumeration); // should not affect iterator
+    object.setProperty("rab", QScriptValue(&engine, "oof"));
+    QScriptValueIterator it(object);
+    it.next();
+    QCOMPARE(it.name(), QLatin1String("foo"));
+    it.remove();
+    QCOMPARE(it.hasPrevious(), false);
+    QCOMPARE(object.property("foo").isValid(), false);
+    QCOMPARE(object.property("rab").toString(), QLatin1String("oof"));
+    it.next();
+    QCOMPARE(it.name(), QLatin1String("rab"));
+    QCOMPARE(it.value().toString(), QLatin1String("oof"));
+    QCOMPARE(it.hasNext(), false);
+    it.remove();
+    QCOMPARE(object.property("rab").isValid(), false);
+    QCOMPARE(it.hasPrevious(), false);
+    QCOMPARE(it.hasNext(), false);
+}
+
+void tst_QScriptValueIterator::removeMixed()
+{
+    // This test checks if QScriptValueIterator behaives correctly if an object's property got deleted
+    // in different way.
+    QScriptEngine engine;
+    QScriptValue object = engine.evaluate("o = new Object; o");
+    object.setProperty("a", QScriptValue(124), QScriptValue::SkipInEnumeration);
+    object.setProperty("b", QScriptValue(816));
+    object.setProperty("c", QScriptValue(3264));
+    QScriptValueIterator it(object);
+    it.next();
+    it.next();
+    QCOMPARE(it.name(), QLatin1String("b"));
+    QCOMPARE(it.hasPrevious(), true);
+    QCOMPARE(it.hasNext(), true);
+    // Remove 'a'
+    object.setProperty("a", QScriptValue());
+    QEXPECT_FAIL("", "That would be a significant behavioral and performance change, new QtScript API should be developed (QTBUG-12087)", Abort);
+    QCOMPARE(it.hasPrevious(), false);
+    QCOMPARE(it.hasNext(), true);
+    // Remove 'c'
+    engine.evaluate("delete o.c");
+    QCOMPARE(it.hasPrevious(), false);
+    QCOMPARE(it.hasNext(), false);
+    // Remove 'b'
+    object.setProperty("b", QScriptValue());
+    QCOMPARE(it.hasPrevious(), false);
+    QCOMPARE(it.hasNext(), false);
+    QCOMPARE(it.name(), QString());
+    QCOMPARE(it.value().toString(), QString());
+
+    // Try to remove a removed property.
+    it.remove();
+    QCOMPARE(it.hasPrevious(), false);
+    QCOMPARE(it.hasNext(), false);
+    QCOMPARE(it.name(), QString());
+    QCOMPARE(it.value().toString(), QString());
+
+    for (int i = 0; i < 2; ++i) {
+        it.next();
+        QCOMPARE(it.hasPrevious(), false);
+        QCOMPARE(it.hasNext(), false);
+        QCOMPARE(it.name(), QString());
+        QCOMPARE(it.value().toString(), QString());
+    }
+
+    for (int i = 0; i < 2; ++i) {
+        it.previous();
+        QCOMPARE(it.hasPrevious(), false);
+        QCOMPARE(it.hasNext(), false);
+        QCOMPARE(it.name(), QString());
+        QCOMPARE(it.value().toString(), QString());
+    }
+}
+
+void tst_QScriptValueIterator::removeUndeletable()
+{
+    // Undeletable property can't be deleted via iterator.
+    QScriptEngine engine;
+    QScriptValue object = engine.evaluate("o = new Object; o");
+    object.setProperty("a", QScriptValue(&engine, 124));
+    object.setProperty("b", QScriptValue(&engine, 816), QScriptValue::Undeletable);
+    QVERIFY(object.property("b").isValid());
+    QScriptValueIterator it(object);
+    it.next();
+    it.next();
+    it.remove();
+    it.toFront();
+    QVERIFY(it.hasNext());
+    QVERIFY(object.property("b").isValid());
+}
+
+void tst_QScriptValueIterator::iterateString()
+{
+    QScriptEngine engine;
+    QScriptValue str = QScriptValue(&engine, QString::fromLatin1("ciao"));
+    QVERIFY(str.isString());
+    QScriptValue obj = str.toObject();
+    int length = obj.property("length").toInt32();
+    QCOMPARE(length, 4);
+    QScriptValueIterator it(obj);
+    for (int i = 0; i < length; ++i) {
+        QCOMPARE(it.hasNext(), true);
+        QString indexStr = QScriptValue(&engine, i).toString();
+        it.next();
+        QCOMPARE(it.name(), indexStr);
+        QCOMPARE(it.flags(), obj.propertyFlags(indexStr));
+        QCOMPARE(it.value().strictlyEquals(obj.property(indexStr)), true);
+    }
+    QVERIFY(it.hasNext());
+    it.next();
+    QCOMPARE(it.name(), QString::fromLatin1("length"));
+    QVERIFY(it.value().isNumber());
+    QCOMPARE(it.value().toInt32(), length);
+    QCOMPARE(it.flags(), QScriptValue::PropertyFlags(QScriptValue::ReadOnly | QScriptValue::SkipInEnumeration | QScriptValue::Undeletable));
+
+    it.previous();
+    QCOMPARE(it.hasPrevious(), length > 0);
+    for (int i = length - 1; i >= 0; --i) {
+        it.previous();
+        QString indexStr = QScriptValue(&engine, i).toString();
+        QCOMPARE(it.name(), indexStr);
+        QCOMPARE(it.flags(), obj.propertyFlags(indexStr));
+        QCOMPARE(it.value().strictlyEquals(obj.property(indexStr)), true);
+        QCOMPARE(it.hasPrevious(), i > 0);
+    }
+    QCOMPARE(it.hasPrevious(), false);
+}
+
+void tst_QScriptValueIterator::assignObjectToIterator()
+{
+    QScriptEngine eng;
+    QScriptValue obj1 = eng.newObject();
+    obj1.setProperty("foo", 123);
+    QScriptValue obj2 = eng.newObject();
+    obj2.setProperty("bar", 456);
+
+    QScriptValueIterator it(obj1);
+    QVERIFY(it.hasNext());
+    it.next();
+    it = obj2;
+    QVERIFY(it.hasNext());
+    it.next();
+    QCOMPARE(it.name(), QString::fromLatin1("bar"));
+
+    it = obj1;
+    QVERIFY(it.hasNext());
+    it.next();
+    QCOMPARE(it.name(), QString::fromLatin1("foo"));
+
+    it = obj2;
+    QVERIFY(it.hasNext());
+    it.next();
+    QCOMPARE(it.name(), QString::fromLatin1("bar"));
+
+    it = obj2;
+    QVERIFY(it.hasNext());
+    it.next();
+    QCOMPARE(it.name(), QString::fromLatin1("bar"));
+}
+
+QTEST_MAIN(tst_QScriptValueIterator)
+#include "tst_qscriptvalueiterator.moc"
+
+#endif // tst_qscriptvalueiterator_h
diff --git a/JavaScriptCore/qt/tests/tests.pro b/JavaScriptCore/qt/tests/tests.pro
index 7c3f590..6d5559b 100644
--- a/JavaScriptCore/qt/tests/tests.pro
+++ b/JavaScriptCore/qt/tests/tests.pro
@@ -1,4 +1,5 @@
 TEMPLATE = subdirs
 SUBDIRS =   qscriptengine \
             qscriptvalue \
+            qscriptvalueiterator \
             qscriptstring

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list