summaryrefslogtreecommitdiffstats
path: root/src/script/qscriptecmaarray.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/script/qscriptecmaarray.cpp')
-rw-r--r--src/script/qscriptecmaarray.cpp777
1 files changed, 777 insertions, 0 deletions
diff --git a/src/script/qscriptecmaarray.cpp b/src/script/qscriptecmaarray.cpp
new file mode 100644
index 0000000000..d068ba6a1a
--- /dev/null
+++ b/src/script/qscriptecmaarray.cpp
@@ -0,0 +1,777 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtScript module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qscriptecmaarray_p.h"
+
+#ifndef QT_NO_SCRIPT
+
+#include "qscriptengine_p.h"
+#include "qscriptvalueimpl_p.h"
+#include "qscriptcontext_p.h"
+#include "qscriptmember_p.h"
+#include "qscriptobject_p.h"
+#include "qscriptclassdata_p.h"
+
+#include <QtCore/QtDebug>
+
+QT_BEGIN_NAMESPACE
+
+namespace QScript { namespace Ecma {
+
+class ArrayClassData: public QScriptClassData
+{
+ QScriptClassInfo *m_classInfo;
+
+public:
+ ArrayClassData(QScriptClassInfo *classInfo);
+ virtual ~ArrayClassData();
+
+ inline QScriptClassInfo *classInfo() const
+ { return m_classInfo; }
+
+ virtual void mark(const QScriptValueImpl &object, int generation);
+ virtual bool resolve(const QScriptValueImpl &object,
+ QScriptNameIdImpl *nameId,
+ QScript::Member *member,
+ QScriptValueImpl *base,
+ QScript::AccessMode mode);
+ virtual bool get(const QScriptValueImpl &obj, const Member &m,
+ QScriptValueImpl *out_value);
+ virtual bool put(QScriptValueImpl *object, const Member &member,
+ const QScriptValueImpl &value);
+ virtual bool removeMember(const QScriptValueImpl &object,
+ const QScript::Member &member);
+ virtual QScriptClassDataIterator *newIterator(const QScriptValueImpl &object);
+};
+
+class ArrayClassDataIterator: public QScriptClassDataIterator
+{
+public:
+ ArrayClassDataIterator(Array::Instance *instance);
+ virtual ~ArrayClassDataIterator();
+
+ virtual bool hasNext() const;
+ virtual void next(QScript::Member *member);
+
+ virtual bool hasPrevious() const;
+ virtual void previous(QScript::Member *member);
+
+ virtual void toFront();
+ virtual void toBack();
+
+private:
+ Array::Instance *m_instance;
+ QList<uint> m_keys;
+ quint32 m_pos;
+};
+
+ArrayClassData::ArrayClassData(QScriptClassInfo *classInfo):
+ m_classInfo(classInfo)
+{
+}
+
+ArrayClassData::~ArrayClassData()
+{
+}
+
+void ArrayClassData::mark(const QScriptValueImpl &object, int generation)
+{
+ Array::Instance *instance = Array::Instance::get(object, classInfo());
+ if (! instance)
+ return;
+
+ instance->value.mark(generation);
+}
+
+bool ArrayClassData::resolve(const QScriptValueImpl &object,
+ QScriptNameIdImpl *nameId,
+ QScript::Member *member,
+ QScriptValueImpl *base,
+ QScript::AccessMode access)
+{
+ QScriptEnginePrivate *eng_p = object.engine();
+
+ Array::Instance *instance = Array::Instance::get(object, classInfo());
+ if (!instance)
+ return false;
+
+ if (nameId == eng_p->idTable()->id_length) {
+ member->native(nameId, /*id=*/ 0,
+ QScriptValue::Undeletable
+ | QScriptValue::SkipInEnumeration);
+ *base = object;
+ return true;
+ }
+
+ QString propertyName = eng_p->toString(nameId);
+ bool isNumber;
+ quint32 pos = propertyName.toUInt(&isNumber);
+
+ if (!isNumber || (pos == 0xFFFFFFFF)
+ || (QScriptValueImpl(pos).toString() != propertyName)) { // ### improve me
+ return false;
+ }
+
+ if ((access == QScript::Read) && ((pos >= instance->value.count()) || !instance->value.at(pos).isValid()))
+ return false;
+
+ member->native(0, pos, /*flags=*/0);
+ *base = object;
+ return true;
+}
+
+bool ArrayClassData::get(const QScriptValueImpl &object,
+ const QScript::Member &member,
+ QScriptValueImpl *result)
+{
+ Q_ASSERT(member.isValid());
+
+ if (! member.isNativeProperty())
+ return false;
+
+ QScriptEnginePrivate *eng = object.engine();
+
+ Array::Instance *instance = Array::Instance::get(object, classInfo());
+ if (! instance)
+ return false;
+
+ if (member.nameId() == eng->idTable()->id_length)
+ *result = QScriptValueImpl(instance->value.count());
+
+ else {
+ quint32 pos = quint32 (member.id());
+
+ if (pos < instance->value.count())
+ *result = instance->value.at(pos);
+ else
+ *result = eng->undefinedValue();
+ }
+
+ return true;
+}
+
+bool ArrayClassData::put(QScriptValueImpl *object,
+ const QScript::Member &member,
+ const QScriptValueImpl &value)
+{
+ Q_ASSERT(object != 0);
+ Q_ASSERT(member.isValid());
+
+ if (! member.isNativeProperty())
+ return false;
+
+ Array::Instance *instance = Array::Instance::get(*object, classInfo());
+ if (! instance)
+ return false;
+
+ QScriptEnginePrivate *eng_p = object->engine();
+
+ if (member.nameId() == eng_p->idTable()->id_length) {
+ qsreal length = value.toNumber();
+ quint32 len = eng_p->toUint32(length);
+ instance->value.resize(len);
+ }
+
+ else if (member.nameId() == 0) {
+ quint32 pos = quint32 (member.id());
+ instance->value.assign(pos, value);
+ }
+
+ return true;
+}
+
+bool ArrayClassData::removeMember(const QScriptValueImpl &object,
+ const QScript::Member &member)
+{
+ if (!member.isNativeProperty() || !member.isDeletable() || (member.nameId() != 0))
+ return false;
+
+ Array::Instance *instance = Array::Instance::get(object, classInfo());
+ if (! instance)
+ return false;
+
+ quint32 pos = quint32 (member.id());
+ if (instance->value.at(pos).isValid())
+ instance->value.assign(pos, QScriptValueImpl());
+ return true;
+}
+
+QScriptClassDataIterator *ArrayClassData::newIterator(const QScriptValueImpl &object)
+{
+ Array::Instance *instance = Array::Instance::get(object, classInfo());
+ return new ArrayClassDataIterator(instance);
+}
+
+ArrayClassDataIterator::ArrayClassDataIterator(Array::Instance *instance)
+{
+ m_instance = instance;
+ toFront();
+}
+
+ArrayClassDataIterator::~ArrayClassDataIterator()
+{
+}
+
+bool ArrayClassDataIterator::hasNext() const
+{
+ quint32 limit = m_keys.isEmpty() ? m_instance->value.size() : quint32(m_keys.size());
+ for (quint32 i = m_pos; i < limit; ++i) {
+ quint32 realI = m_keys.isEmpty() ? i : m_keys.at(i);
+ if (m_instance->value.at(realI).isValid())
+ return true;
+ }
+ return false;
+}
+
+void ArrayClassDataIterator::next(QScript::Member *member)
+{
+ quint32 limit = m_keys.isEmpty() ? m_instance->value.size() : quint32(m_keys.size());
+ for (quint32 i = m_pos; i < limit; ++i) {
+ quint32 realI = m_keys.isEmpty() ? i : m_keys.at(i);
+ if (m_instance->value.at(realI).isValid()) {
+ member->native(/*nameId=*/0, realI, /*flags=*/0);
+ m_pos = i + 1;
+ return;
+ }
+ }
+ member->invalidate();
+}
+
+bool ArrayClassDataIterator::hasPrevious() const
+{
+ for (quint32 i = m_pos - 1; i != 0xFFFFFFFF; --i) {
+ quint32 realI = m_keys.isEmpty() ? i : m_keys.at(i);
+ if (m_instance->value.at(realI).isValid())
+ return true;
+ }
+ return false;
+}
+
+void ArrayClassDataIterator::previous(QScript::Member *member)
+{
+ for (quint32 i = m_pos - 1; i != 0xFFFFFFFF; --i) {
+ quint32 realI = m_keys.isEmpty() ? i : m_keys.at(i);
+ if (m_instance->value.at(realI).isValid()) {
+ member->native(/*nameId=*/ 0, realI, /*flags=*/0);
+ m_pos = i;
+ return;
+ }
+ }
+ member->invalidate();
+}
+
+void ArrayClassDataIterator::toFront()
+{
+ m_keys = m_instance->value.keys();
+ m_pos = 0;
+}
+
+void ArrayClassDataIterator::toBack()
+{
+ m_keys = m_instance->value.keys();
+ m_pos = m_keys.isEmpty() ? m_instance->value.count() : m_keys.size();
+}
+
+
+
+Array::Array(QScriptEnginePrivate *eng):
+ Core(eng, QLatin1String("Array"), QScriptClassInfo::ArrayType)
+{
+ classInfo()->setData(new ArrayClassData(classInfo()));
+
+ newArray(&publicPrototype, QScript::Array(eng));
+
+ eng->newConstructor(&ctor, this, publicPrototype);
+
+ addPrototypeFunction(QLatin1String("toString"), method_toString, 0);
+ addPrototypeFunction(QLatin1String("toLocaleString"), method_toLocaleString, 0);
+ addPrototypeFunction(QLatin1String("concat"), method_concat, 1);
+ addPrototypeFunction(QLatin1String("join"), method_join, 1);
+ addPrototypeFunction(QLatin1String("pop"), method_pop, 0);
+ addPrototypeFunction(QLatin1String("push"), method_push, 1);
+ addPrototypeFunction(QLatin1String("reverse"), method_reverse, 0);
+ addPrototypeFunction(QLatin1String("shift"), method_shift, 0);
+ addPrototypeFunction(QLatin1String("slice"), method_slice, 2);
+ addPrototypeFunction(QLatin1String("sort"), method_sort, 1);
+ addPrototypeFunction(QLatin1String("splice"), method_splice, 2);
+ addPrototypeFunction(QLatin1String("unshift"), method_unshift, 1);
+}
+
+Array::~Array()
+{
+}
+
+void Array::execute(QScriptContextPrivate *context)
+{
+#ifndef Q_SCRIPT_NO_EVENT_NOTIFY
+ engine()->notifyFunctionEntry(context);
+#endif
+ QScript::Array value(engine());
+
+ if (context->argumentCount() == 1 && context->argument(0).isNumber()) {
+ qsreal size = context->argument(0).toNumber();
+ quint32 isize = QScriptEnginePrivate::toUint32(size);
+
+ if (size != qsreal(isize)) {
+ context->throwError(QScriptContext::RangeError, QLatin1String("invalid array length"));
+ return;
+ }
+
+ value.resize(isize);
+ } else {
+ for (int i = 0; i < context->argumentCount(); ++i) {
+ value.assign(i, context->argument(i));
+ }
+ }
+
+ if (context->isCalledAsConstructor()) {
+ QScriptValueImpl &object = context->m_thisObject;
+ object.setClassInfo(classInfo());
+ object.setPrototype(publicPrototype);
+ initArray(&object, value);
+ } else {
+ newArray(&context->m_result, value);
+ }
+
+#ifndef Q_SCRIPT_NO_EVENT_NOTIFY
+ engine()->notifyFunctionExit(context);
+#endif
+}
+
+void Array::newArray(QScriptValueImpl *result, const QScript::Array &value)
+{
+ engine()->newObject(result, publicPrototype, classInfo());
+ initArray(result, value);
+}
+
+void Array::initArray(QScriptValueImpl *result, const QScript::Array &value)
+{
+ Instance *instance = new Instance(engine());
+ instance->value = value;
+ result->setObjectData(instance);
+}
+
+QScriptValueImpl Array::method_toString(QScriptContextPrivate *context,
+ QScriptEnginePrivate *eng,
+ QScriptClassInfo *classInfo)
+{
+ return method_join(context, eng, classInfo); // ### fixme
+}
+
+QScriptValueImpl Array::method_toLocaleString(QScriptContextPrivate *context,
+ QScriptEnginePrivate *eng,
+ QScriptClassInfo *classInfo)
+{
+ return method_toString(context, eng, classInfo);
+}
+
+QScriptValueImpl Array::method_concat(QScriptContextPrivate *context,
+ QScriptEnginePrivate *eng,
+ QScriptClassInfo *classInfo)
+{
+ QScript::Array result(eng);
+
+ if (Instance *instance = Instance::get(context->thisObject(), classInfo))
+ result = instance->value;
+
+ else {
+ QString v = context->thisObject().toString();
+ result.assign(0, QScriptValueImpl(eng, v));
+ }
+
+ for (int i = 0; i < context->argumentCount(); ++i) {
+ quint32 k = result.size();
+ QScriptValueImpl arg = context->argument(i);
+
+ if (Instance *elt = Instance::get(arg, classInfo))
+ result.concat(elt->value);
+
+ else
+ result.assign(k, QScriptValueImpl(eng, arg.toString()));
+ }
+
+ return eng->newArray(result);
+}
+
+QScriptValueImpl Array::method_join(QScriptContextPrivate *context,
+ QScriptEnginePrivate *eng,
+ QScriptClassInfo *)
+{
+ QScriptValueImpl arg = context->argument(0);
+
+ QString r4;
+ if (arg.isUndefined())
+ r4 = QLatin1String(",");
+ else
+ r4 = arg.toString();
+
+ QScriptValueImpl self = context->thisObject();
+
+ QScriptNameIdImpl *id_length = eng->idTable()->id_length;
+ QScriptValueImpl length = self.property(id_length);
+ qsreal r1 = length.isValid() ? length.toNumber() : 0;
+ quint32 r2 = QScriptEnginePrivate::toUint32(r1);
+
+ if (! r2)
+ return QScriptValueImpl(eng, QString());
+
+ if (eng->visitedArrayElements.contains(self.objectValue())) {
+ // avoid infinite recursion
+ return QScriptValueImpl(eng, QString());
+ }
+ eng->visitedArrayElements.insert(self.objectValue());
+
+ QString R;
+
+ QScriptValueImpl r6 = self.property(QLatin1String("0"));
+ if (r6.isValid() && !(r6.isUndefined() || r6.isNull()))
+ R = r6.toString();
+
+ for (quint32 k = 1; k < r2; ++k) {
+ R += r4;
+
+ QScriptNameIdImpl *name = eng->nameId(QScriptValueImpl(k).toString());
+ QScriptValueImpl r12 = self.property(name);
+
+ if (r12.isValid() && ! (r12.isUndefined() || r12.isNull()))
+ R += r12.toString();
+ }
+
+ eng->visitedArrayElements.remove(self.objectValue());
+ return QScriptValueImpl(eng, R);
+}
+
+QScriptValueImpl Array::method_pop(QScriptContextPrivate *context,
+ QScriptEnginePrivate *eng,
+ QScriptClassInfo *classInfo)
+{
+ QScriptValueImpl self = context->thisObject();
+ if (Instance *instance = Instance::get(self, classInfo)) {
+ QScriptValueImpl elt = instance->value.pop();
+ if (! elt.isValid())
+ elt = eng->undefinedValue();
+
+ return elt;
+ }
+
+ QScriptNameIdImpl *id_length = eng->idTable()->id_length;
+
+ QScriptValueImpl r1 = self.property(id_length);
+ quint32 r2 = r1.toUInt32();
+ if (! r2) {
+ self.setProperty(id_length, QScriptValueImpl(0));
+ return eng->undefinedValue();
+ }
+ QScriptNameIdImpl *r6 = eng->nameId(QScriptValueImpl(r2 - 1).toString());
+ QScriptValueImpl r7 = self.property(r6);
+ self.deleteProperty(r6);
+ self.setProperty(id_length, QScriptValueImpl(r2 - 1));
+ if (!r7.isValid())
+ return eng->undefinedValue();
+ return r7;
+}
+
+QScriptValueImpl Array::method_push(QScriptContextPrivate *context,
+ QScriptEnginePrivate *eng,
+ QScriptClassInfo *classInfo)
+{
+ QScriptValueImpl self = context->thisObject();
+ if (Instance *instance = Instance::get(self, classInfo)) {
+ uint pos = instance->value.size();
+ for (int i = 0; i < context->argumentCount(); ++i) {
+ QScriptValueImpl val = context->argument(i);
+ if (pos == 0xFFFFFFFF) {
+ self.setProperty(pos++, val);
+ self.setProperty(eng->idTable()->id_length, 0);
+ } else {
+ instance->value.assign(pos++, val);
+ }
+ }
+ return QScriptValueImpl(pos);
+ }
+
+ QScriptNameIdImpl *id_length = eng->idTable()->id_length;
+ QScriptValueImpl r1 = self.property(id_length);
+ quint32 n = r1.toUInt32();
+ for (int index = 0; index < context->argumentCount(); ++index, ++n) {
+ QScriptValueImpl r3 = context->argument(index);
+ QScriptNameIdImpl *name = eng->nameId(QScriptValueImpl(n).toString());
+ self.setProperty(name, r3);
+ }
+ QScriptValueImpl r(n);
+ self.setProperty(id_length, r);
+ return r;
+}
+
+QScriptValueImpl Array::method_reverse(QScriptContextPrivate *context,
+ QScriptEnginePrivate *eng,
+ QScriptClassInfo *classInfo)
+{
+ QScriptValueImpl self = context->thisObject();
+ if (Instance *instance = Instance::get(self, classInfo)) {
+ int lo = 0, hi = instance->value.count () - 1;
+
+ for (; lo < hi; ++lo, --hi) {
+ QScriptValueImpl tmp = instance->value.at(lo);
+ instance->value.assign(lo, instance->value.at(hi));
+ instance->value.assign(hi, tmp);
+ }
+
+ } else {
+ QScriptNameIdImpl *id_length = eng->idTable()->id_length;
+
+ QScriptValueImpl lengthValue = self.property(id_length);
+ quint32 length = 0;
+ if (lengthValue.isValid())
+ length = QScriptEnginePrivate::toUint32(lengthValue.toNumber());
+ const quint32 m = length / 2;
+ for (quint32 i = 0; i < m; ++i) {
+ quint32 j = length - i - 1;
+
+ QScriptNameIdImpl *iid = eng->nameId(QScriptValueImpl(i).toString());
+ QScriptNameIdImpl *jid = eng->nameId(QScriptValueImpl(j).toString());
+
+ QScript::Member imember;
+ QScriptValueImpl ibase;
+ QScriptValueImpl ival;
+ bool iok = self.resolve(iid, &imember, &ibase, QScriptValue::ResolvePrototype, QScript::ReadWrite);
+ if (iok)
+ ibase.get(iid, &ival);
+ else
+ ival = eng->undefinedValue();
+
+ QScript::Member jmember;
+ QScriptValueImpl jbase;
+ QScriptValueImpl jval;
+ bool jok = self.resolve(jid, &jmember, &jbase, QScriptValue::ResolvePrototype, QScript::ReadWrite);
+ if (jok)
+ jbase.get(jid, &jval);
+ else
+ jval = eng->undefinedValue();
+
+ if (!jok) {
+ if (iok) {
+ if (eng->strictlyEquals(ibase, self))
+ ibase.removeMember(imember);
+ self.setProperty(jid, ival);
+ }
+ } else if (!iok) {
+ self.setProperty(iid, jval);
+ if (eng->strictlyEquals(jbase, self))
+ jbase.removeMember(jmember);
+ } else {
+ if (eng->strictlyEquals(self, ibase))
+ self.put(imember, jval);
+ else
+ self.setProperty(iid, jval);
+ if (eng->strictlyEquals(self, jbase))
+ self.put(jmember, ival);
+ else
+ self.setProperty(jid, ival);
+ }
+ }
+ }
+
+ return context->thisObject();
+}
+
+QScriptValueImpl Array::method_shift(QScriptContextPrivate *context,
+ QScriptEnginePrivate *eng,
+ QScriptClassInfo *)
+{
+ QScriptNameIdImpl *id_length = eng->idTable()->id_length;
+
+ QScriptValueImpl self = context->thisObject();
+ quint32 length = self.property(id_length).toUInt32();
+ if (length == 0) {
+ self.setProperty(id_length, QScriptValueImpl(0));
+ return eng->undefinedValue();
+ }
+
+ QScript::Member member;
+ QScriptValueImpl base;
+
+ QScriptValueImpl result = self.property(QLatin1String("0"));
+ if (! result.isValid())
+ result = eng->undefinedValue();
+
+ for (quint32 index = 1; index < length; ++index) {
+ QScriptNameIdImpl *k = eng->nameId(QScriptValueImpl(index).toString());
+ QScriptNameIdImpl *k1 = eng->nameId(QScriptValueImpl(index - 1).toString());
+
+ QScriptValueImpl v = self.property(k);
+ QScriptValueImpl v1 = self.property(k1);
+
+ if (v.isValid())
+ self.setProperty(k1, v);
+
+ else if (v1.isValid() && self.resolve(k1, &member, &base, QScriptValue::ResolveLocal, QScript::ReadWrite))
+ self.removeMember(member);
+ }
+
+ QScriptValueImpl len = QScriptValueImpl(length - 1);
+
+ if (self.resolve(eng->nameId(len.toString()), &member, &base, QScriptValue::ResolveLocal, QScript::ReadWrite))
+ self.removeMember(member);
+
+ self.setProperty(id_length, len);
+ return (result);
+}
+
+QScriptValueImpl Array::method_slice(QScriptContextPrivate *context,
+ QScriptEnginePrivate *eng,
+ QScriptClassInfo *)
+{
+ QScript::Array result(eng);
+
+ QScriptValueImpl start = context->argument(0);
+ QScriptValueImpl end = context->argument(1);
+
+ QScriptValueImpl self = context->thisObject();
+ QScriptNameIdImpl *id_length = eng->idTable()->id_length;
+ qsreal r2 = self.property(id_length).toNumber();
+ quint32 r3 = QScriptEnginePrivate::toUint32(r2);
+ qint32 r4 = qint32 (start.toInteger());
+ quint32 r5 = r4 < 0 ? qMax(quint32(r3 + r4), quint32(0)) : qMin(quint32(r4), r3);
+ quint32 k = r5;
+ qint32 r7 = end.isUndefined() ? r3 : qint32 (end.toInteger());
+ quint32 r8 = r7 < 0 ? qMax(quint32(r3 + r7), quint32(0)) : qMin(quint32(r7), r3);
+ quint32 n = 0;
+ for (; k < r8; ++k) {
+ QString r11 = QScriptValueImpl(k).toString();
+ QScriptValueImpl v = self.property(r11);
+ if (v.isValid())
+ result.assign(n++, v);
+ }
+ return eng->newArray(result);
+}
+
+QScriptValueImpl Array::method_sort(QScriptContextPrivate *context,
+ QScriptEnginePrivate *,
+ QScriptClassInfo *classInfo)
+{
+ QScriptValueImpl self = context->thisObject();
+ QScriptValueImpl comparefn = context->argument(0);
+ if (Instance *instance = Instance::get(self, classInfo)) {
+ instance->value.sort(comparefn);
+ return context->thisObject();
+ }
+ return context->throwNotImplemented(QLatin1String("Array.prototype.sort"));
+}
+
+QScriptValueImpl Array::method_splice(QScriptContextPrivate *context,
+ QScriptEnginePrivate *eng,
+ QScriptClassInfo *classInfo)
+{
+ if (context->argumentCount() < 2)
+ return eng->undefinedValue();
+
+ QScriptValueImpl self = context->thisObject();
+
+ qsreal start = context->argument(0).toInteger();
+ qsreal deleteCount = context->argument(1).toInteger();
+
+ QScriptValueImpl arrayCtor = eng->globalObject().property(QLatin1String("Array"));
+ QScriptValueImpl a = arrayCtor.construct();
+
+ if (Instance *instance = Instance::get(self, classInfo)) {
+ QVector<QScriptValueImpl> items;
+ for (int i = 2; i < context->argumentCount(); ++i)
+ items << context->argument(i);
+ Instance *otherInstance = Instance::get(a, classInfo);
+ Q_ASSERT(otherInstance);
+ instance->value.splice(start, deleteCount, items, otherInstance->value);
+ return a;
+ }
+
+ return context->throwNotImplemented(QLatin1String("Array.prototype.splice"));
+}
+
+QScriptValueImpl Array::method_unshift(QScriptContextPrivate *context,
+ QScriptEnginePrivate *eng,
+ QScriptClassInfo *)
+{
+ QScriptValueImpl self = context->thisObject();
+
+ QScriptNameIdImpl *id_length = eng->idTable()->id_length;
+ QScriptValueImpl r1 = self.property(id_length);
+ quint32 r2 = r1.isValid() ? QScriptEnginePrivate::toUint32(r1.toNumber()) : 0;
+ quint32 r3 = quint32 (context->argumentCount());
+ quint32 k = r2;
+ for (; k != 0; --k) {
+ QScriptNameIdImpl *r6 = eng->nameId(QScriptValueImpl(k - 1).toString());
+ QScriptNameIdImpl *r7 = eng->nameId(QScriptValueImpl(k + r3 - 1).toString());
+ QScriptValueImpl r8 = self.property(r6);
+ if (r8.isValid())
+ self.setProperty(r7, r8);
+
+ else {
+ QScript::Member member;
+ QScriptValueImpl base;
+
+ if (self.resolve(r7, &member, &base, QScriptValue::ResolveLocal, QScript::ReadWrite))
+ self.removeMember(member);
+ }
+ }
+
+ for (k = 0; k < r3; ++k) {
+ QScriptValueImpl r16 = context->argument(k);
+ QScriptNameIdImpl *r17 = eng->nameId(QScriptValueImpl(k).toString());
+ self.setProperty(r17, r16);
+ }
+ QScriptValueImpl r(r2 + r3);
+ self.setProperty(id_length, r);
+ return (r);
+}
+
+Array::Instance *Array::Instance::get(const QScriptValueImpl &object, QScriptClassInfo *klass)
+{
+ if (! klass || klass == object.classInfo())
+ return static_cast<Instance*> (object.objectData());
+
+ return 0;
+}
+
+} } // namespace QScript::Ecma
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_SCRIPT