source: trunk/src/script/qscriptecmaarray.cpp@ 428

Last change on this file since 428 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 25.2 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the QtScript module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you are unsure which license is appropriate for your use, please
37** contact the sales department at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qscriptecmaarray_p.h"
43
44#ifndef QT_NO_SCRIPT
45
46#include "qscriptengine_p.h"
47#include "qscriptvalueimpl_p.h"
48#include "qscriptcontext_p.h"
49#include "qscriptmember_p.h"
50#include "qscriptobject_p.h"
51#include "qscriptclassdata_p.h"
52
53#include <QtCore/QtDebug>
54
55QT_BEGIN_NAMESPACE
56
57namespace QScript { namespace Ecma {
58
59class ArrayClassData: public QScriptClassData
60{
61 QScriptClassInfo *m_classInfo;
62
63public:
64 ArrayClassData(QScriptClassInfo *classInfo);
65 virtual ~ArrayClassData();
66
67 inline QScriptClassInfo *classInfo() const
68 { return m_classInfo; }
69
70 virtual void mark(const QScriptValueImpl &object, int generation);
71 virtual bool resolve(const QScriptValueImpl &object,
72 QScriptNameIdImpl *nameId,
73 QScript::Member *member,
74 QScriptValueImpl *base,
75 QScript::AccessMode mode);
76 virtual bool get(const QScriptValueImpl &obj, const Member &m,
77 QScriptValueImpl *out_value);
78 virtual bool put(QScriptValueImpl *object, const Member &member,
79 const QScriptValueImpl &value);
80 virtual bool removeMember(const QScriptValueImpl &object,
81 const QScript::Member &member);
82 virtual QScriptClassDataIterator *newIterator(const QScriptValueImpl &object);
83};
84
85class ArrayClassDataIterator: public QScriptClassDataIterator
86{
87public:
88 ArrayClassDataIterator(Array::Instance *instance);
89 virtual ~ArrayClassDataIterator();
90
91 virtual bool hasNext() const;
92 virtual void next(QScript::Member *member);
93
94 virtual bool hasPrevious() const;
95 virtual void previous(QScript::Member *member);
96
97 virtual void toFront();
98 virtual void toBack();
99
100private:
101 Array::Instance *m_instance;
102 QList<uint> m_keys;
103 quint32 m_pos;
104};
105
106ArrayClassData::ArrayClassData(QScriptClassInfo *classInfo):
107 m_classInfo(classInfo)
108{
109}
110
111ArrayClassData::~ArrayClassData()
112{
113}
114
115void ArrayClassData::mark(const QScriptValueImpl &object, int generation)
116{
117 Array::Instance *instance = Array::Instance::get(object, classInfo());
118 if (! instance)
119 return;
120
121 instance->value.mark(generation);
122}
123
124bool ArrayClassData::resolve(const QScriptValueImpl &object,
125 QScriptNameIdImpl *nameId,
126 QScript::Member *member,
127 QScriptValueImpl *base,
128 QScript::AccessMode access)
129{
130 QScriptEnginePrivate *eng_p = object.engine();
131
132 Array::Instance *instance = Array::Instance::get(object, classInfo());
133 if (!instance)
134 return false;
135
136 if (nameId == eng_p->idTable()->id_length) {
137 member->native(nameId, /*id=*/ 0,
138 QScriptValue::Undeletable
139 | QScriptValue::SkipInEnumeration);
140 *base = object;
141 return true;
142 }
143
144 QString propertyName = eng_p->toString(nameId);
145 bool isNumber;
146 quint32 pos = propertyName.toUInt(&isNumber);
147
148 if (!isNumber || (pos == 0xFFFFFFFF)
149 || (QScriptValueImpl(pos).toString() != propertyName)) { // ### improve me
150 return false;
151 }
152
153 if ((access == QScript::Read) && ((pos >= instance->value.count()) || !instance->value.at(pos).isValid()))
154 return false;
155
156 member->native(0, pos, /*flags=*/0);
157 *base = object;
158 return true;
159}
160
161bool ArrayClassData::get(const QScriptValueImpl &object,
162 const QScript::Member &member,
163 QScriptValueImpl *result)
164{
165 Q_ASSERT(member.isValid());
166
167 if (! member.isNativeProperty())
168 return false;
169
170 QScriptEnginePrivate *eng = object.engine();
171
172 Array::Instance *instance = Array::Instance::get(object, classInfo());
173 if (! instance)
174 return false;
175
176 if (member.nameId() == eng->idTable()->id_length)
177 *result = QScriptValueImpl(instance->value.count());
178
179 else {
180 quint32 pos = quint32 (member.id());
181
182 if (pos < instance->value.count())
183 *result = instance->value.at(pos);
184 else
185 *result = eng->undefinedValue();
186 }
187
188 return true;
189}
190
191bool ArrayClassData::put(QScriptValueImpl *object,
192 const QScript::Member &member,
193 const QScriptValueImpl &value)
194{
195 Q_ASSERT(object != 0);
196 Q_ASSERT(member.isValid());
197
198 if (! member.isNativeProperty())
199 return false;
200
201 Array::Instance *instance = Array::Instance::get(*object, classInfo());
202 if (! instance)
203 return false;
204
205 QScriptEnginePrivate *eng_p = object->engine();
206
207 if (member.nameId() == eng_p->idTable()->id_length) {
208 qsreal length = value.toNumber();
209 quint32 len = eng_p->toUint32(length);
210 instance->value.resize(len);
211 }
212
213 else if (member.nameId() == 0) {
214 quint32 pos = quint32 (member.id());
215 instance->value.assign(pos, value);
216 }
217
218 return true;
219}
220
221bool ArrayClassData::removeMember(const QScriptValueImpl &object,
222 const QScript::Member &member)
223{
224 if (!member.isNativeProperty() || !member.isDeletable() || (member.nameId() != 0))
225 return false;
226
227 Array::Instance *instance = Array::Instance::get(object, classInfo());
228 if (! instance)
229 return false;
230
231 quint32 pos = quint32 (member.id());
232 if (instance->value.at(pos).isValid())
233 instance->value.assign(pos, QScriptValueImpl());
234 return true;
235}
236
237QScriptClassDataIterator *ArrayClassData::newIterator(const QScriptValueImpl &object)
238{
239 Array::Instance *instance = Array::Instance::get(object, classInfo());
240 return new ArrayClassDataIterator(instance);
241}
242
243ArrayClassDataIterator::ArrayClassDataIterator(Array::Instance *instance)
244{
245 m_instance = instance;
246 toFront();
247}
248
249ArrayClassDataIterator::~ArrayClassDataIterator()
250{
251}
252
253bool ArrayClassDataIterator::hasNext() const
254{
255 quint32 limit = m_keys.isEmpty() ? m_instance->value.size() : quint32(m_keys.size());
256 for (quint32 i = m_pos; i < limit; ++i) {
257 quint32 realI = m_keys.isEmpty() ? i : m_keys.at(i);
258 if (m_instance->value.at(realI).isValid())
259 return true;
260 }
261 return false;
262}
263
264void ArrayClassDataIterator::next(QScript::Member *member)
265{
266 quint32 limit = m_keys.isEmpty() ? m_instance->value.size() : quint32(m_keys.size());
267 for (quint32 i = m_pos; i < limit; ++i) {
268 quint32 realI = m_keys.isEmpty() ? i : m_keys.at(i);
269 if (m_instance->value.at(realI).isValid()) {
270 member->native(/*nameId=*/0, realI, /*flags=*/0);
271 m_pos = i + 1;
272 return;
273 }
274 }
275 member->invalidate();
276}
277
278bool ArrayClassDataIterator::hasPrevious() const
279{
280 for (quint32 i = m_pos - 1; i != 0xFFFFFFFF; --i) {
281 quint32 realI = m_keys.isEmpty() ? i : m_keys.at(i);
282 if (m_instance->value.at(realI).isValid())
283 return true;
284 }
285 return false;
286}
287
288void ArrayClassDataIterator::previous(QScript::Member *member)
289{
290 for (quint32 i = m_pos - 1; i != 0xFFFFFFFF; --i) {
291 quint32 realI = m_keys.isEmpty() ? i : m_keys.at(i);
292 if (m_instance->value.at(realI).isValid()) {
293 member->native(/*nameId=*/ 0, realI, /*flags=*/0);
294 m_pos = i;
295 return;
296 }
297 }
298 member->invalidate();
299}
300
301void ArrayClassDataIterator::toFront()
302{
303 m_keys = m_instance->value.keys();
304 m_pos = 0;
305}
306
307void ArrayClassDataIterator::toBack()
308{
309 m_keys = m_instance->value.keys();
310 m_pos = m_keys.isEmpty() ? m_instance->value.count() : m_keys.size();
311}
312
313
314
315Array::Array(QScriptEnginePrivate *eng):
316 Core(eng, QLatin1String("Array"), QScriptClassInfo::ArrayType)
317{
318 classInfo()->setData(new ArrayClassData(classInfo()));
319
320 newArray(&publicPrototype, QScript::Array(eng));
321
322 eng->newConstructor(&ctor, this, publicPrototype);
323
324 addPrototypeFunction(QLatin1String("toString"), method_toString, 0);
325 addPrototypeFunction(QLatin1String("toLocaleString"), method_toLocaleString, 0);
326 addPrototypeFunction(QLatin1String("concat"), method_concat, 1);
327 addPrototypeFunction(QLatin1String("join"), method_join, 1);
328 addPrototypeFunction(QLatin1String("pop"), method_pop, 0);
329 addPrototypeFunction(QLatin1String("push"), method_push, 1);
330 addPrototypeFunction(QLatin1String("reverse"), method_reverse, 0);
331 addPrototypeFunction(QLatin1String("shift"), method_shift, 0);
332 addPrototypeFunction(QLatin1String("slice"), method_slice, 2);
333 addPrototypeFunction(QLatin1String("sort"), method_sort, 1);
334 addPrototypeFunction(QLatin1String("splice"), method_splice, 2);
335 addPrototypeFunction(QLatin1String("unshift"), method_unshift, 1);
336}
337
338Array::~Array()
339{
340}
341
342void Array::execute(QScriptContextPrivate *context)
343{
344#ifndef Q_SCRIPT_NO_EVENT_NOTIFY
345 engine()->notifyFunctionEntry(context);
346#endif
347 QScript::Array value(engine());
348
349 if (context->argumentCount() == 1 && context->argument(0).isNumber()) {
350 qsreal size = context->argument(0).toNumber();
351 quint32 isize = QScriptEnginePrivate::toUint32(size);
352
353 if (size != qsreal(isize)) {
354 context->throwError(QScriptContext::RangeError, QLatin1String("invalid array length"));
355 return;
356 }
357
358 value.resize(isize);
359 } else {
360 for (int i = 0; i < context->argumentCount(); ++i) {
361 value.assign(i, context->argument(i));
362 }
363 }
364
365 if (context->isCalledAsConstructor()) {
366 QScriptValueImpl &object = context->m_thisObject;
367 object.setClassInfo(classInfo());
368 object.setPrototype(publicPrototype);
369 initArray(&object, value);
370 } else {
371 newArray(&context->m_result, value);
372 }
373
374#ifndef Q_SCRIPT_NO_EVENT_NOTIFY
375 engine()->notifyFunctionExit(context);
376#endif
377}
378
379void Array::newArray(QScriptValueImpl *result, const QScript::Array &value)
380{
381 engine()->newObject(result, publicPrototype, classInfo());
382 initArray(result, value);
383}
384
385void Array::initArray(QScriptValueImpl *result, const QScript::Array &value)
386{
387 Instance *instance = new Instance(engine());
388 instance->value = value;
389 result->setObjectData(instance);
390}
391
392QScriptValueImpl Array::method_toString(QScriptContextPrivate *context,
393 QScriptEnginePrivate *eng,
394 QScriptClassInfo *classInfo)
395{
396 return method_join(context, eng, classInfo); // ### fixme
397}
398
399QScriptValueImpl Array::method_toLocaleString(QScriptContextPrivate *context,
400 QScriptEnginePrivate *eng,
401 QScriptClassInfo *classInfo)
402{
403 return method_toString(context, eng, classInfo);
404}
405
406QScriptValueImpl Array::method_concat(QScriptContextPrivate *context,
407 QScriptEnginePrivate *eng,
408 QScriptClassInfo *classInfo)
409{
410 QScript::Array result(eng);
411
412 if (Instance *instance = Instance::get(context->thisObject(), classInfo))
413 result = instance->value;
414
415 else {
416 QString v = context->thisObject().toString();
417 result.assign(0, QScriptValueImpl(eng, v));
418 }
419
420 for (int i = 0; i < context->argumentCount(); ++i) {
421 quint32 k = result.size();
422 QScriptValueImpl arg = context->argument(i);
423
424 if (Instance *elt = Instance::get(arg, classInfo))
425 result.concat(elt->value);
426
427 else
428 result.assign(k, QScriptValueImpl(eng, arg.toString()));
429 }
430
431 return eng->newArray(result);
432}
433
434QScriptValueImpl Array::method_join(QScriptContextPrivate *context,
435 QScriptEnginePrivate *eng,
436 QScriptClassInfo *)
437{
438 QScriptValueImpl arg = context->argument(0);
439
440 QString r4;
441 if (arg.isUndefined())
442 r4 = QLatin1String(",");
443 else
444 r4 = arg.toString();
445
446 QScriptValueImpl self = context->thisObject();
447
448 QScriptNameIdImpl *id_length = eng->idTable()->id_length;
449 QScriptValueImpl length = self.property(id_length);
450 qsreal r1 = length.isValid() ? length.toNumber() : 0;
451 quint32 r2 = QScriptEnginePrivate::toUint32(r1);
452
453 if (! r2)
454 return QScriptValueImpl(eng, QString());
455
456 if (eng->visitedArrayElements.contains(self.objectValue())) {
457 // avoid infinite recursion
458 return QScriptValueImpl(eng, QString());
459 }
460 eng->visitedArrayElements.insert(self.objectValue());
461
462 QString R;
463
464 QScriptValueImpl r6 = self.property(QLatin1String("0"));
465 if (r6.isValid() && !(r6.isUndefined() || r6.isNull()))
466 R = r6.toString();
467
468 for (quint32 k = 1; k < r2; ++k) {
469 R += r4;
470
471 QScriptNameIdImpl *name = eng->nameId(QScriptValueImpl(k).toString());
472 QScriptValueImpl r12 = self.property(name);
473
474 if (r12.isValid() && ! (r12.isUndefined() || r12.isNull()))
475 R += r12.toString();
476 }
477
478 eng->visitedArrayElements.remove(self.objectValue());
479 return QScriptValueImpl(eng, R);
480}
481
482QScriptValueImpl Array::method_pop(QScriptContextPrivate *context,
483 QScriptEnginePrivate *eng,
484 QScriptClassInfo *classInfo)
485{
486 QScriptValueImpl self = context->thisObject();
487 if (Instance *instance = Instance::get(self, classInfo)) {
488 QScriptValueImpl elt = instance->value.pop();
489 if (! elt.isValid())
490 elt = eng->undefinedValue();
491
492 return elt;
493 }
494
495 QScriptNameIdImpl *id_length = eng->idTable()->id_length;
496
497 QScriptValueImpl r1 = self.property(id_length);
498 quint32 r2 = r1.toUInt32();
499 if (! r2) {
500 self.setProperty(id_length, QScriptValueImpl(0));
501 return eng->undefinedValue();
502 }
503 QScriptNameIdImpl *r6 = eng->nameId(QScriptValueImpl(r2 - 1).toString());
504 QScriptValueImpl r7 = self.property(r6);
505 self.deleteProperty(r6);
506 self.setProperty(id_length, QScriptValueImpl(r2 - 1));
507 if (!r7.isValid())
508 return eng->undefinedValue();
509 return r7;
510}
511
512QScriptValueImpl Array::method_push(QScriptContextPrivate *context,
513 QScriptEnginePrivate *eng,
514 QScriptClassInfo *classInfo)
515{
516 QScriptValueImpl self = context->thisObject();
517 if (Instance *instance = Instance::get(self, classInfo)) {
518 uint pos = instance->value.size();
519 for (int i = 0; i < context->argumentCount(); ++i) {
520 QScriptValueImpl val = context->argument(i);
521 if (pos == 0xFFFFFFFF) {
522 self.setProperty(pos++, val);
523 self.setProperty(eng->idTable()->id_length, 0);
524 } else {
525 instance->value.assign(pos++, val);
526 }
527 }
528 return QScriptValueImpl(pos);
529 }
530
531 QScriptNameIdImpl *id_length = eng->idTable()->id_length;
532 QScriptValueImpl r1 = self.property(id_length);
533 quint32 n = r1.toUInt32();
534 for (int index = 0; index < context->argumentCount(); ++index, ++n) {
535 QScriptValueImpl r3 = context->argument(index);
536 QScriptNameIdImpl *name = eng->nameId(QScriptValueImpl(n).toString());
537 self.setProperty(name, r3);
538 }
539 QScriptValueImpl r(n);
540 self.setProperty(id_length, r);
541 return r;
542}
543
544QScriptValueImpl Array::method_reverse(QScriptContextPrivate *context,
545 QScriptEnginePrivate *eng,
546 QScriptClassInfo *classInfo)
547{
548 QScriptValueImpl self = context->thisObject();
549 if (Instance *instance = Instance::get(self, classInfo)) {
550 int lo = 0, hi = instance->value.count () - 1;
551
552 for (; lo < hi; ++lo, --hi) {
553 QScriptValueImpl tmp = instance->value.at(lo);
554 instance->value.assign(lo, instance->value.at(hi));
555 instance->value.assign(hi, tmp);
556 }
557
558 } else {
559 QScriptNameIdImpl *id_length = eng->idTable()->id_length;
560
561 QScriptValueImpl lengthValue = self.property(id_length);
562 quint32 length = 0;
563 if (lengthValue.isValid())
564 length = QScriptEnginePrivate::toUint32(lengthValue.toNumber());
565 const quint32 m = length / 2;
566 for (quint32 i = 0; i < m; ++i) {
567 quint32 j = length - i - 1;
568
569 QScriptNameIdImpl *iid = eng->nameId(QScriptValueImpl(i).toString());
570 QScriptNameIdImpl *jid = eng->nameId(QScriptValueImpl(j).toString());
571
572 QScript::Member imember;
573 QScriptValueImpl ibase;
574 QScriptValueImpl ival;
575 bool iok = self.resolve(iid, &imember, &ibase, QScriptValue::ResolvePrototype, QScript::ReadWrite);
576 if (iok)
577 ibase.get(iid, &ival);
578 else
579 ival = eng->undefinedValue();
580
581 QScript::Member jmember;
582 QScriptValueImpl jbase;
583 QScriptValueImpl jval;
584 bool jok = self.resolve(jid, &jmember, &jbase, QScriptValue::ResolvePrototype, QScript::ReadWrite);
585 if (jok)
586 jbase.get(jid, &jval);
587 else
588 jval = eng->undefinedValue();
589
590 if (!jok) {
591 if (iok) {
592 if (eng->strictlyEquals(ibase, self))
593 ibase.removeMember(imember);
594 self.setProperty(jid, ival);
595 }
596 } else if (!iok) {
597 self.setProperty(iid, jval);
598 if (eng->strictlyEquals(jbase, self))
599 jbase.removeMember(jmember);
600 } else {
601 if (eng->strictlyEquals(self, ibase))
602 self.put(imember, jval);
603 else
604 self.setProperty(iid, jval);
605 if (eng->strictlyEquals(self, jbase))
606 self.put(jmember, ival);
607 else
608 self.setProperty(jid, ival);
609 }
610 }
611 }
612
613 return context->thisObject();
614}
615
616QScriptValueImpl Array::method_shift(QScriptContextPrivate *context,
617 QScriptEnginePrivate *eng,
618 QScriptClassInfo *)
619{
620 QScriptNameIdImpl *id_length = eng->idTable()->id_length;
621
622 QScriptValueImpl self = context->thisObject();
623 quint32 length = self.property(id_length).toUInt32();
624 if (length == 0) {
625 self.setProperty(id_length, QScriptValueImpl(0));
626 return eng->undefinedValue();
627 }
628
629 QScript::Member member;
630 QScriptValueImpl base;
631
632 QScriptValueImpl result = self.property(QLatin1String("0"));
633 if (! result.isValid())
634 result = eng->undefinedValue();
635
636 for (quint32 index = 1; index < length; ++index) {
637 QScriptNameIdImpl *k = eng->nameId(QScriptValueImpl(index).toString());
638 QScriptNameIdImpl *k1 = eng->nameId(QScriptValueImpl(index - 1).toString());
639
640 QScriptValueImpl v = self.property(k);
641 QScriptValueImpl v1 = self.property(k1);
642
643 if (v.isValid())
644 self.setProperty(k1, v);
645
646 else if (v1.isValid() && self.resolve(k1, &member, &base, QScriptValue::ResolveLocal, QScript::ReadWrite))
647 self.removeMember(member);
648 }
649
650 QScriptValueImpl len = QScriptValueImpl(length - 1);
651
652 if (self.resolve(eng->nameId(len.toString()), &member, &base, QScriptValue::ResolveLocal, QScript::ReadWrite))
653 self.removeMember(member);
654
655 self.setProperty(id_length, len);
656 return (result);
657}
658
659QScriptValueImpl Array::method_slice(QScriptContextPrivate *context,
660 QScriptEnginePrivate *eng,
661 QScriptClassInfo *)
662{
663 QScript::Array result(eng);
664
665 QScriptValueImpl start = context->argument(0);
666 QScriptValueImpl end = context->argument(1);
667
668 QScriptValueImpl self = context->thisObject();
669 QScriptNameIdImpl *id_length = eng->idTable()->id_length;
670 qsreal r2 = self.property(id_length).toNumber();
671 quint32 r3 = QScriptEnginePrivate::toUint32(r2);
672 qint32 r4 = qint32 (start.toInteger());
673 quint32 r5 = r4 < 0 ? qMax(quint32(r3 + r4), quint32(0)) : qMin(quint32(r4), r3);
674 quint32 k = r5;
675 qint32 r7 = end.isUndefined() ? r3 : qint32 (end.toInteger());
676 quint32 r8 = r7 < 0 ? qMax(quint32(r3 + r7), quint32(0)) : qMin(quint32(r7), r3);
677 quint32 n = 0;
678 for (; k < r8; ++k) {
679 QString r11 = QScriptValueImpl(k).toString();
680 QScriptValueImpl v = self.property(r11);
681 if (v.isValid())
682 result.assign(n++, v);
683 }
684 return eng->newArray(result);
685}
686
687QScriptValueImpl Array::method_sort(QScriptContextPrivate *context,
688 QScriptEnginePrivate *,
689 QScriptClassInfo *classInfo)
690{
691 QScriptValueImpl self = context->thisObject();
692 QScriptValueImpl comparefn = context->argument(0);
693 if (Instance *instance = Instance::get(self, classInfo)) {
694 instance->value.sort(comparefn);
695 return context->thisObject();
696 }
697 return context->throwNotImplemented(QLatin1String("Array.prototype.sort"));
698}
699
700QScriptValueImpl Array::method_splice(QScriptContextPrivate *context,
701 QScriptEnginePrivate *eng,
702 QScriptClassInfo *classInfo)
703{
704 if (context->argumentCount() < 2)
705 return eng->undefinedValue();
706
707 QScriptValueImpl self = context->thisObject();
708
709 qsreal start = context->argument(0).toInteger();
710 qsreal deleteCount = context->argument(1).toInteger();
711
712 QScriptValueImpl arrayCtor = eng->globalObject().property(QLatin1String("Array"));
713 QScriptValueImpl a = arrayCtor.construct();
714
715 if (Instance *instance = Instance::get(self, classInfo)) {
716 QVector<QScriptValueImpl> items;
717 for (int i = 2; i < context->argumentCount(); ++i)
718 items << context->argument(i);
719 Instance *otherInstance = Instance::get(a, classInfo);
720 Q_ASSERT(otherInstance);
721 instance->value.splice(start, deleteCount, items, otherInstance->value);
722 return a;
723 }
724
725 return context->throwNotImplemented(QLatin1String("Array.prototype.splice"));
726}
727
728QScriptValueImpl Array::method_unshift(QScriptContextPrivate *context,
729 QScriptEnginePrivate *eng,
730 QScriptClassInfo *)
731{
732 QScriptValueImpl self = context->thisObject();
733
734 QScriptNameIdImpl *id_length = eng->idTable()->id_length;
735 QScriptValueImpl r1 = self.property(id_length);
736 quint32 r2 = r1.isValid() ? QScriptEnginePrivate::toUint32(r1.toNumber()) : 0;
737 quint32 r3 = quint32 (context->argumentCount());
738 quint32 k = r2;
739 for (; k != 0; --k) {
740 QScriptNameIdImpl *r6 = eng->nameId(QScriptValueImpl(k - 1).toString());
741 QScriptNameIdImpl *r7 = eng->nameId(QScriptValueImpl(k + r3 - 1).toString());
742 QScriptValueImpl r8 = self.property(r6);
743 if (r8.isValid())
744 self.setProperty(r7, r8);
745
746 else {
747 QScript::Member member;
748 QScriptValueImpl base;
749
750 if (self.resolve(r7, &member, &base, QScriptValue::ResolveLocal, QScript::ReadWrite))
751 self.removeMember(member);
752 }
753 }
754
755 for (k = 0; k < r3; ++k) {
756 QScriptValueImpl r16 = context->argument(k);
757 QScriptNameIdImpl *r17 = eng->nameId(QScriptValueImpl(k).toString());
758 self.setProperty(r17, r16);
759 }
760 QScriptValueImpl r(r2 + r3);
761 self.setProperty(id_length, r);
762 return (r);
763}
764
765Array::Instance *Array::Instance::get(const QScriptValueImpl &object, QScriptClassInfo *klass)
766{
767 if (! klass || klass == object.classInfo())
768 return static_cast<Instance*> (object.objectData());
769
770 return 0;
771}
772
773} } // namespace QScript::Ecma
774
775QT_END_NAMESPACE
776
777#endif // QT_NO_SCRIPT
Note: See TracBrowser for help on using the repository browser.