Remove TESTED_CLASS/TESTED_FILES comments from tests.
[profile/ivi/qtdeclarative.git] / tests / auto / declarative / qjsvalue / tst_qjsvalue.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the test suite of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 **
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 **
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
29 **
30 ** Other Usage
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "tst_qjsvalue.h"
43 #include <QtWidgets/QPushButton>
44
45 QT_BEGIN_NAMESPACE
46 extern bool qt_script_isJITEnabled();
47 QT_END_NAMESPACE
48
49 tst_QJSValue::tst_QJSValue()
50     : engine(0)
51 {
52 }
53
54 tst_QJSValue::~tst_QJSValue()
55 {
56     if (engine)
57         delete engine;
58 }
59
60 void tst_QJSValue::ctor_invalid()
61 {
62     QJSEngine eng;
63     {
64         QJSValue v;
65         QCOMPARE(v.isValid(), false);
66         QCOMPARE(v.engine(), (QJSEngine *)0);
67     }
68 }
69
70 void tst_QJSValue::ctor_undefinedWithEngine()
71 {
72     QJSEngine eng;
73     {
74         QJSValue v(&eng, QJSValue::UndefinedValue);
75         QCOMPARE(v.isValid(), true);
76         QCOMPARE(v.isUndefined(), true);
77         QCOMPARE(v.isObject(), false);
78         QCOMPARE(v.engine(), &eng);
79     }
80 }
81
82 void tst_QJSValue::ctor_nullWithEngine()
83 {
84     QJSEngine eng;
85     {
86         QJSValue v(&eng, QJSValue::NullValue);
87         QCOMPARE(v.isValid(), true);
88         QCOMPARE(v.isNull(), true);
89         QCOMPARE(v.isObject(), false);
90         QCOMPARE(v.engine(), &eng);
91     }
92 }
93
94 void tst_QJSValue::ctor_boolWithEngine()
95 {
96     QJSEngine eng;
97     {
98         QJSValue v(&eng, false);
99         QCOMPARE(v.isValid(), true);
100         QCOMPARE(v.isBoolean(), true);
101         QCOMPARE(v.isBool(), true);
102         QCOMPARE(v.isObject(), false);
103         QCOMPARE(v.toBoolean(), false);
104         QCOMPARE(v.engine(), &eng);
105     }
106 }
107
108 void tst_QJSValue::ctor_intWithEngine()
109 {
110     QJSEngine eng;
111     {
112         QJSValue v(&eng, int(1));
113         QCOMPARE(v.isValid(), true);
114         QCOMPARE(v.isNumber(), true);
115         QCOMPARE(v.isObject(), false);
116         QCOMPARE(v.toNumber(), 1.0);
117         QCOMPARE(v.engine(), &eng);
118     }
119 }
120
121 void tst_QJSValue::ctor_int()
122 {
123     {
124         QJSValue v(int(0x43211234));
125         QVERIFY(v.isNumber());
126         QCOMPARE(v.toInt32(), 0x43211234);
127     }
128     {
129         QJSValue v(int(1));
130         QCOMPARE(v.isValid(), true);
131         QCOMPARE(v.isNumber(), true);
132         QCOMPARE(v.isObject(), false);
133         QCOMPARE(v.toNumber(), 1.0);
134         QCOMPARE(v.engine(), (QJSEngine *)0);
135     }
136 }
137
138 void tst_QJSValue::ctor_uintWithEngine()
139 {
140     QJSEngine eng;
141     {
142         QJSValue v(&eng, uint(1));
143         QCOMPARE(v.isValid(), true);
144         QCOMPARE(v.isNumber(), true);
145         QCOMPARE(v.isObject(), false);
146         QCOMPARE(v.toNumber(), 1.0);
147         QCOMPARE(v.engine(), &eng);
148     }
149 }
150
151 void tst_QJSValue::ctor_uint()
152 {
153     {
154         QJSValue v(uint(0x43211234));
155         QVERIFY(v.isNumber());
156         QCOMPARE(v.toUInt32(), uint(0x43211234));
157     }
158     {
159         QJSValue v(uint(1));
160         QCOMPARE(v.isValid(), true);
161         QCOMPARE(v.isNumber(), true);
162         QCOMPARE(v.isObject(), false);
163         QCOMPARE(v.toNumber(), 1.0);
164         QCOMPARE(v.engine(), (QJSEngine *)0);
165     }
166 }
167
168 void tst_QJSValue::ctor_floatWithEngine()
169 {
170     QJSEngine eng;
171     {
172         QJSValue v(&eng, 1.0);
173         QCOMPARE(v.isValid(), true);
174         QCOMPARE(v.isNumber(), true);
175         QCOMPARE(v.isObject(), false);
176         QCOMPARE(v.toNumber(), 1.0);
177         QCOMPARE(v.engine(), &eng);
178     }
179 }
180
181 void tst_QJSValue::ctor_float()
182 {
183     {
184         QJSValue v(12345678910.5);
185         QVERIFY(v.isNumber());
186         QCOMPARE(v.toNumber(), 12345678910.5);
187     }
188     {
189         QJSValue v(1.0);
190         QCOMPARE(v.isValid(), true);
191         QCOMPARE(v.isNumber(), true);
192         QCOMPARE(v.isObject(), false);
193         QCOMPARE(v.toNumber(), 1.0);
194         QCOMPARE(v.engine(), (QJSEngine *)0);
195     }
196 }
197
198 void tst_QJSValue::ctor_stringWithEngine()
199 {
200     QJSEngine eng;
201     {
202         QJSValue v(&eng, QLatin1String("ciao"));
203         QCOMPARE(v.isValid(), true);
204         QCOMPARE(v.isString(), true);
205         QCOMPARE(v.isObject(), false);
206         QCOMPARE(v.toString(), QLatin1String("ciao"));
207         QCOMPARE(v.engine(), &eng);
208     }
209 }
210
211 void tst_QJSValue::ctor_string()
212 {
213     {
214         QJSValue v(QString("ciao"));
215         QCOMPARE(v.isValid(), true);
216         QCOMPARE(v.isString(), true);
217         QCOMPARE(v.isObject(), false);
218         QCOMPARE(v.toString(), QLatin1String("ciao"));
219         QCOMPARE(v.engine(), (QJSEngine *)0);
220     }
221     {
222         QJSValue v("ciao");
223         QCOMPARE(v.isValid(), true);
224         QCOMPARE(v.isString(), true);
225         QCOMPARE(v.isObject(), false);
226         QCOMPARE(v.toString(), QLatin1String("ciao"));
227         QCOMPARE(v.engine(), (QJSEngine *)0);
228     }
229 }
230
231 void tst_QJSValue::ctor_copyAndAssignWithEngine()
232 {
233     QJSEngine eng;
234     // copy constructor, operator=
235     {
236         QJSValue v(&eng, 1.0);
237         QJSValue v2(v);
238         QCOMPARE(v2.strictlyEquals(v), true);
239         QCOMPARE(v2.engine(), &eng);
240
241         QJSValue v3(v);
242         QCOMPARE(v3.strictlyEquals(v), true);
243         QCOMPARE(v3.strictlyEquals(v2), true);
244         QCOMPARE(v3.engine(), &eng);
245
246         QJSValue v4(&eng, 2.0);
247         QCOMPARE(v4.strictlyEquals(v), false);
248         v3 = v4;
249         QCOMPARE(v3.strictlyEquals(v), false);
250         QCOMPARE(v3.strictlyEquals(v4), true);
251
252         v2 = QJSValue();
253         QCOMPARE(v2.strictlyEquals(v), false);
254         QCOMPARE(v.toNumber(), 1.0);
255
256         QJSValue v5(v);
257         QCOMPARE(v5.strictlyEquals(v), true);
258         v = QJSValue();
259         QCOMPARE(v5.strictlyEquals(v), false);
260         QCOMPARE(v5.toNumber(), 1.0);
261     }
262 }
263
264 void tst_QJSValue::ctor_undefined()
265 {
266     QJSValue v(QJSValue::UndefinedValue);
267     QCOMPARE(v.isValid(), true);
268     QCOMPARE(v.isUndefined(), true);
269     QCOMPARE(v.isObject(), false);
270     QCOMPARE(v.engine(), (QJSEngine *)0);
271 }
272
273 void tst_QJSValue::ctor_null()
274 {
275     QJSValue v(QJSValue::NullValue);
276     QCOMPARE(v.isValid(), true);
277     QCOMPARE(v.isNull(), true);
278     QCOMPARE(v.isObject(), false);
279     QCOMPARE(v.engine(), (QJSEngine *)0);
280 }
281
282 void tst_QJSValue::ctor_bool()
283 {
284     QJSValue v(false);
285     QCOMPARE(v.isValid(), true);
286     QCOMPARE(v.isBoolean(), true);
287     QCOMPARE(v.isBool(), true);
288     QCOMPARE(v.isObject(), false);
289     QCOMPARE(v.toBoolean(), false);
290     QCOMPARE(v.engine(), (QJSEngine *)0);
291 }
292
293 void tst_QJSValue::ctor_copyAndAssign()
294 {
295     QJSValue v(1.0);
296     QJSValue v2(v);
297     QCOMPARE(v2.strictlyEquals(v), true);
298     QCOMPARE(v2.engine(), (QJSEngine *)0);
299
300     QJSValue v3(v);
301     QCOMPARE(v3.strictlyEquals(v), true);
302     QCOMPARE(v3.strictlyEquals(v2), true);
303     QCOMPARE(v3.engine(), (QJSEngine *)0);
304
305     QJSValue v4(2.0);
306     QCOMPARE(v4.strictlyEquals(v), false);
307     v3 = v4;
308     QCOMPARE(v3.strictlyEquals(v), false);
309     QCOMPARE(v3.strictlyEquals(v4), true);
310
311     v2 = QJSValue();
312     QCOMPARE(v2.strictlyEquals(v), false);
313     QCOMPARE(v.toNumber(), 1.0);
314
315     QJSValue v5(v);
316     QCOMPARE(v5.strictlyEquals(v), true);
317     v = QJSValue();
318     QCOMPARE(v5.strictlyEquals(v), false);
319     QCOMPARE(v5.toNumber(), 1.0);
320 }
321
322 void tst_QJSValue::ctor_nullEngine()
323 {
324     // 0 engine
325     QVERIFY(QJSValue(0, QJSValue::UndefinedValue).isUndefined());
326     QVERIFY(QJSValue(0, QJSValue::NullValue).isNull());
327     QVERIFY(QJSValue(0, false).isBool());
328     QVERIFY(QJSValue(0, int(1)).isNumber());
329     QVERIFY(QJSValue(0, uint(1)).isNumber());
330     QVERIFY(QJSValue(0, 1.0).isNumber());
331     QVERIFY(QJSValue(0, QString("ciao")).isString());
332 }
333
334 #if 0 // FIXME: No c-style callbacks currently
335 static QJSValue myFunction(QScriptContext *, QScriptEngine *eng)
336 {
337     return eng->undefinedValue();
338 }
339 #endif
340
341 void tst_QJSValue::toString()
342 {
343     QJSEngine eng;
344
345     QJSValue undefined = eng.undefinedValue();
346     QCOMPARE(undefined.toString(), QString("undefined"));
347     QCOMPARE(qjsvalue_cast<QString>(undefined), QString());
348
349     QJSValue null = eng.nullValue();
350     QCOMPARE(null.toString(), QString("null"));
351     QCOMPARE(qjsvalue_cast<QString>(null), QString());
352
353     {
354         QJSValue falskt = QJSValue(&eng, false);
355         QCOMPARE(falskt.toString(), QString("false"));
356         QCOMPARE(qjsvalue_cast<QString>(falskt), QString("false"));
357
358         QJSValue sant = QJSValue(&eng, true);
359         QCOMPARE(sant.toString(), QString("true"));
360         QCOMPARE(qjsvalue_cast<QString>(sant), QString("true"));
361     }
362     {
363         QJSValue number = QJSValue(&eng, 123);
364         QCOMPARE(number.toString(), QString("123"));
365         QCOMPARE(qjsvalue_cast<QString>(number), QString("123"));
366     }
367     {
368         QJSValue number = QJSValue(&eng, 6.37e-8);
369         QCOMPARE(number.toString(), QString("6.37e-8"));
370     }
371     {
372         QJSValue number = QJSValue(&eng, -6.37e-8);
373         QCOMPARE(number.toString(), QString("-6.37e-8"));
374
375         QJSValue str = QJSValue(&eng, QString("ciao"));
376         QCOMPARE(str.toString(), QString("ciao"));
377         QCOMPARE(qjsvalue_cast<QString>(str), QString("ciao"));
378     }
379
380     QJSValue object = eng.newObject();
381     QCOMPARE(object.toString(), QString("[object Object]"));
382     QCOMPARE(qjsvalue_cast<QString>(object), QString("[object Object]"));
383
384     // FIXME: No c-style callbacks currently
385 #if 0
386     QJSValue fun = eng.newFunction(myFunction);
387     QCOMPARE(fun.toString().simplified(), QString("function () { [native code] }"));
388     QCOMPARE(qscriptvalue_cast<QString>(fun).simplified(), QString("function () { [native code] }"));
389 #endif
390
391     // toString() that throws exception
392     {
393         QJSValue objectObject = eng.evaluate(
394             "(function(){"
395             "  o = { };"
396             "  o.toString = function() { throw new Error('toString'); };"
397             "  return o;"
398             "})()");
399         QCOMPARE(objectObject.toString(), QLatin1String("Error: toString"));
400         QVERIFY(eng.hasUncaughtException());
401         QCOMPARE(eng.uncaughtException().toString(), QLatin1String("Error: toString"));
402     }
403     {
404         eng.clearExceptions();
405         QJSValue objectObject = eng.evaluate(
406             "(function(){"
407             "  var f = function() {};"
408             "  f.prototype = Date;"
409             "  return new f;"
410             "})()");
411         QVERIFY(!eng.hasUncaughtException());
412         QVERIFY(objectObject.isObject());
413         QCOMPARE(objectObject.toString(), QString::fromLatin1("TypeError: Function.prototype.toString is not generic"));
414         QVERIFY(eng.hasUncaughtException());
415         eng.clearExceptions();
416     }
417
418     QJSValue inv = QJSValue();
419     QCOMPARE(inv.toString(), QString());
420
421     // V2 constructors
422     {
423         QJSValue falskt = QJSValue(false);
424         QCOMPARE(falskt.toString(), QString("false"));
425         QCOMPARE(qjsvalue_cast<QString>(falskt), QString("false"));
426
427         QJSValue sant = QJSValue(true);
428         QCOMPARE(sant.toString(), QString("true"));
429         QCOMPARE(qjsvalue_cast<QString>(sant), QString("true"));
430
431         QJSValue number = QJSValue(123);
432         QCOMPARE(number.toString(), QString("123"));
433         QCOMPARE(qjsvalue_cast<QString>(number), QString("123"));
434
435         QJSValue number2(int(0x43211234));
436         QCOMPARE(number2.toString(), QString("1126240820"));
437
438         QJSValue str = QJSValue(QString("ciao"));
439         QCOMPARE(str.toString(), QString("ciao"));
440         QCOMPARE(qjsvalue_cast<QString>(str), QString("ciao"));
441     }
442
443     // variant should use internal valueOf(), then fall back to QVariant::toString(),
444     // then fall back to "QVariant(typename)"
445     QJSValue variant = eng.newVariant(123);
446     QVERIFY(variant.isVariant());
447     QCOMPARE(variant.toString(), QString::fromLatin1("123"));
448     variant = eng.newVariant(QByteArray("hello"));
449     QVERIFY(variant.isVariant());
450     QCOMPARE(variant.toString(), QString::fromLatin1("hello"));
451     variant = eng.newVariant(QVariant(QPoint(10, 20)));
452     QVERIFY(variant.isVariant());
453     QCOMPARE(variant.toString(), QString::fromLatin1("QVariant(QPoint)"));
454     variant = eng.newVariant(QUrl());
455     QVERIFY(variant.toString().isEmpty());
456 }
457
458 void tst_QJSValue::toNumber()
459 {
460     QJSEngine eng;
461
462     QJSValue undefined = eng.undefinedValue();
463     QCOMPARE(qIsNaN(undefined.toNumber()), true);
464     QCOMPARE(qIsNaN(qjsvalue_cast<qreal>(undefined)), true);
465
466     QJSValue null = eng.nullValue();
467     QCOMPARE(null.toNumber(), 0.0);
468     QCOMPARE(qjsvalue_cast<qreal>(null), 0.0);
469
470     {
471         QJSValue falskt = QJSValue(&eng, false);
472         QCOMPARE(falskt.toNumber(), 0.0);
473         QCOMPARE(qjsvalue_cast<qreal>(falskt), 0.0);
474
475         QJSValue sant = QJSValue(&eng, true);
476         QCOMPARE(sant.toNumber(), 1.0);
477         QCOMPARE(qjsvalue_cast<qreal>(sant), 1.0);
478
479         QJSValue number = QJSValue(&eng, 123.0);
480         QCOMPARE(number.toNumber(), 123.0);
481         QCOMPARE(qjsvalue_cast<qreal>(number), 123.0);
482
483         QJSValue str = QJSValue(&eng, QString("ciao"));
484         QCOMPARE(qIsNaN(str.toNumber()), true);
485         QCOMPARE(qIsNaN(qjsvalue_cast<qreal>(str)), true);
486
487         QJSValue str2 = QJSValue(&eng, QString("123"));
488         QCOMPARE(str2.toNumber(), 123.0);
489         QCOMPARE(qjsvalue_cast<qreal>(str2), 123.0);
490     }
491
492     QJSValue object = eng.newObject();
493     QCOMPARE(qIsNaN(object.toNumber()), true);
494     QCOMPARE(qIsNaN(qjsvalue_cast<qreal>(object)), true);
495
496     // FIXME: No c-style callbacks currently
497 #if 0
498     QJSValue fun = eng.newFunction(myFunction);
499     QCOMPARE(qIsNaN(fun.toNumber()), true);
500     QCOMPARE(qIsNaN(qscriptvalue_cast<qreal>(fun)), true);
501 #endif
502
503     QJSValue inv = QJSValue();
504     QCOMPARE(inv.toNumber(), 0.0);
505     QCOMPARE(qjsvalue_cast<qreal>(inv), 0.0);
506
507     // V2 constructors
508     {
509         QJSValue falskt = QJSValue(false);
510         QCOMPARE(falskt.toNumber(), 0.0);
511         QCOMPARE(qjsvalue_cast<qreal>(falskt), 0.0);
512
513         QJSValue sant = QJSValue(true);
514         QCOMPARE(sant.toNumber(), 1.0);
515         QCOMPARE(qjsvalue_cast<qreal>(sant), 1.0);
516
517         QJSValue number = QJSValue(123.0);
518         QCOMPARE(number.toNumber(), 123.0);
519         QCOMPARE(qjsvalue_cast<qreal>(number), 123.0);
520
521         QJSValue number2(int(0x43211234));
522         QCOMPARE(number2.toNumber(), 1126240820.0);
523
524         QJSValue str = QJSValue(QString("ciao"));
525         QCOMPARE(qIsNaN(str.toNumber()), true);
526         QCOMPARE(qIsNaN(qjsvalue_cast<qreal>(str)), true);
527
528         QJSValue str2 = QJSValue(QString("123"));
529         QCOMPARE(str2.toNumber(), 123.0);
530         QCOMPARE(qjsvalue_cast<qreal>(str2), 123.0);
531     }
532 }
533
534 void tst_QJSValue::toBoolean() // deprecated
535 {
536     QJSEngine eng;
537
538     QJSValue undefined = eng.undefinedValue();
539     QCOMPARE(undefined.toBoolean(), false);
540     QCOMPARE(qjsvalue_cast<bool>(undefined), false);
541
542     QJSValue null = eng.nullValue();
543     QCOMPARE(null.toBoolean(), false);
544     QCOMPARE(qjsvalue_cast<bool>(null), false);
545
546     {
547         QJSValue falskt = QJSValue(&eng, false);
548         QCOMPARE(falskt.toBoolean(), false);
549         QCOMPARE(qjsvalue_cast<bool>(falskt), false);
550
551         QJSValue sant = QJSValue(&eng, true);
552         QCOMPARE(sant.toBoolean(), true);
553         QCOMPARE(qjsvalue_cast<bool>(sant), true);
554
555         QJSValue number = QJSValue(&eng, 0.0);
556         QCOMPARE(number.toBoolean(), false);
557         QCOMPARE(qjsvalue_cast<bool>(number), false);
558
559         QJSValue number2 = QJSValue(&eng, qSNaN());
560         QCOMPARE(number2.toBoolean(), false);
561         QCOMPARE(qjsvalue_cast<bool>(number2), false);
562
563         QJSValue number3 = QJSValue(&eng, 123.0);
564         QCOMPARE(number3.toBoolean(), true);
565         QCOMPARE(qjsvalue_cast<bool>(number3), true);
566
567         QJSValue number4 = QJSValue(&eng, -456.0);
568         QCOMPARE(number4.toBoolean(), true);
569         QCOMPARE(qjsvalue_cast<bool>(number4), true);
570
571         QJSValue str = QJSValue(&eng, QString(""));
572         QCOMPARE(str.toBoolean(), false);
573         QCOMPARE(qjsvalue_cast<bool>(str), false);
574
575         QJSValue str2 = QJSValue(&eng, QString("123"));
576         QCOMPARE(str2.toBoolean(), true);
577         QCOMPARE(qjsvalue_cast<bool>(str2), true);
578     }
579
580     QJSValue object = eng.newObject();
581     QCOMPARE(object.toBoolean(), true);
582     QCOMPARE(qjsvalue_cast<bool>(object), true);
583
584     // FIXME: No c-style callbacks currently
585 #if 0
586     QJSValue fun = eng.newFunction(myFunction);
587     QCOMPARE(fun.toBoolean(), true);
588     QCOMPARE(qscriptvalue_cast<bool>(fun), true);
589 #endif
590
591     QJSValue inv = QJSValue();
592     QCOMPARE(inv.toBoolean(), false);
593     QCOMPARE(qjsvalue_cast<bool>(inv), false);
594
595     // V2 constructors
596     {
597         QJSValue falskt = QJSValue(false);
598         QCOMPARE(falskt.toBoolean(), false);
599         QCOMPARE(qjsvalue_cast<bool>(falskt), false);
600
601         QJSValue sant = QJSValue(true);
602         QCOMPARE(sant.toBoolean(), true);
603         QCOMPARE(qjsvalue_cast<bool>(sant), true);
604
605         QJSValue number = QJSValue(0.0);
606         QCOMPARE(number.toBoolean(), false);
607         QCOMPARE(qjsvalue_cast<bool>(number), false);
608
609         QJSValue number2 = QJSValue(qSNaN());
610         QCOMPARE(number2.toBoolean(), false);
611         QCOMPARE(qjsvalue_cast<bool>(number2), false);
612
613         QJSValue number3 = QJSValue(123.0);
614         QCOMPARE(number3.toBoolean(), true);
615         QCOMPARE(qjsvalue_cast<bool>(number3), true);
616
617         QJSValue number4 = QJSValue(-456.0);
618         QCOMPARE(number4.toBoolean(), true);
619         QCOMPARE(qjsvalue_cast<bool>(number4), true);
620
621         QJSValue number5 = QJSValue(0x43211234);
622         QCOMPARE(number5.toBoolean(), true);
623
624         QJSValue str = QJSValue(QString(""));
625         QCOMPARE(str.toBoolean(), false);
626         QCOMPARE(qjsvalue_cast<bool>(str), false);
627
628         QJSValue str2 = QJSValue(QString("123"));
629         QCOMPARE(str2.toBoolean(), true);
630         QCOMPARE(qjsvalue_cast<bool>(str2), true);
631     }
632 }
633
634 void tst_QJSValue::toBool()
635 {
636     QJSEngine eng;
637
638     QJSValue undefined = eng.undefinedValue();
639     QCOMPARE(undefined.toBool(), false);
640     QCOMPARE(qjsvalue_cast<bool>(undefined), false);
641
642     QJSValue null = eng.nullValue();
643     QCOMPARE(null.toBool(), false);
644     QCOMPARE(qjsvalue_cast<bool>(null), false);
645
646     {
647         QJSValue falskt = QJSValue(&eng, false);
648         QCOMPARE(falskt.toBool(), false);
649         QCOMPARE(qjsvalue_cast<bool>(falskt), false);
650
651         QJSValue sant = QJSValue(&eng, true);
652         QCOMPARE(sant.toBool(), true);
653         QCOMPARE(qjsvalue_cast<bool>(sant), true);
654
655         QJSValue number = QJSValue(&eng, 0.0);
656         QCOMPARE(number.toBool(), false);
657         QCOMPARE(qjsvalue_cast<bool>(number), false);
658
659         QJSValue number2 = QJSValue(&eng, qSNaN());
660         QCOMPARE(number2.toBool(), false);
661         QCOMPARE(qjsvalue_cast<bool>(number2), false);
662
663         QJSValue number3 = QJSValue(&eng, 123.0);
664         QCOMPARE(number3.toBool(), true);
665         QCOMPARE(qjsvalue_cast<bool>(number3), true);
666
667         QJSValue number4 = QJSValue(&eng, -456.0);
668         QCOMPARE(number4.toBool(), true);
669         QCOMPARE(qjsvalue_cast<bool>(number4), true);
670
671         QJSValue str = QJSValue(&eng, QString(""));
672         QCOMPARE(str.toBool(), false);
673         QCOMPARE(qjsvalue_cast<bool>(str), false);
674
675         QJSValue str2 = QJSValue(&eng, QString("123"));
676         QCOMPARE(str2.toBool(), true);
677         QCOMPARE(qjsvalue_cast<bool>(str2), true);
678     }
679
680     QJSValue object = eng.newObject();
681     QCOMPARE(object.toBool(), true);
682     QCOMPARE(qjsvalue_cast<bool>(object), true);
683
684     // FIXME: No c-style callbacks currently
685 #if 0
686     QJSValue fun = eng.newFunction(myFunction);
687     QCOMPARE(fun.toBool(), true);
688     QCOMPARE(qscriptvalue_cast<bool>(fun), true);
689 #endif
690
691     QJSValue inv = QJSValue();
692     QCOMPARE(inv.toBool(), false);
693     QCOMPARE(qjsvalue_cast<bool>(inv), false);
694
695     // V2 constructors
696     {
697         QJSValue falskt = QJSValue(false);
698         QCOMPARE(falskt.toBool(), false);
699         QCOMPARE(qjsvalue_cast<bool>(falskt), false);
700
701         QJSValue sant = QJSValue(true);
702         QCOMPARE(sant.toBool(), true);
703         QCOMPARE(qjsvalue_cast<bool>(sant), true);
704
705         QJSValue number = QJSValue(0.0);
706         QCOMPARE(number.toBool(), false);
707         QCOMPARE(qjsvalue_cast<bool>(number), false);
708
709         QJSValue number2 = QJSValue(qSNaN());
710         QCOMPARE(number2.toBool(), false);
711         QCOMPARE(qjsvalue_cast<bool>(number2), false);
712
713         QJSValue number3 = QJSValue(123.0);
714         QCOMPARE(number3.toBool(), true);
715         QCOMPARE(qjsvalue_cast<bool>(number3), true);
716
717         QJSValue number4 = QJSValue(-456.0);
718         QCOMPARE(number4.toBool(), true);
719         QCOMPARE(qjsvalue_cast<bool>(number4), true);
720
721         QJSValue number5 = QJSValue(0x43211234);
722         QCOMPARE(number5.toBool(), true);
723
724         QJSValue str = QJSValue(QString(""));
725         QCOMPARE(str.toBool(), false);
726         QCOMPARE(qjsvalue_cast<bool>(str), false);
727
728         QJSValue str2 = QJSValue(QString("123"));
729         QCOMPARE(str2.toBool(), true);
730         QCOMPARE(qjsvalue_cast<bool>(str2), true);
731     }
732 }
733
734 void tst_QJSValue::toInteger()
735 {
736     QJSEngine eng;
737
738     {
739         QJSValue number = QJSValue(&eng, 123.0);
740         QCOMPARE(number.toInteger(), 123.0);
741
742         QJSValue number2 = QJSValue(&eng, qSNaN());
743         QCOMPARE(number2.toInteger(), 0.0);
744
745         QJSValue number3 = QJSValue(&eng, qInf());
746         QCOMPARE(qIsInf(number3.toInteger()), true);
747
748         QJSValue number4 = QJSValue(&eng, 0.5);
749         QCOMPARE(number4.toInteger(), 0.0);
750
751         QJSValue number5 = QJSValue(&eng, 123.5);
752         QCOMPARE(number5.toInteger(), 123.0);
753
754         QJSValue number6 = QJSValue(&eng, -456.5);
755         QCOMPARE(number6.toInteger(), -456.0);
756
757         QJSValue str = QJSValue(&eng, QLatin1String("123.0"));
758         QCOMPARE(str.toInteger(), 123.0);
759
760         QJSValue str2 = QJSValue(&eng, QLatin1String("NaN"));
761         QCOMPARE(str2.toInteger(), 0.0);
762
763         QJSValue str3 = QJSValue(&eng, QLatin1String("Infinity"));
764         QCOMPARE(qIsInf(str3.toInteger()), true);
765
766         QJSValue str4 = QJSValue(&eng, QLatin1String("0.5"));
767         QCOMPARE(str4.toInteger(), 0.0);
768
769         QJSValue str5 = QJSValue(&eng, QLatin1String("123.5"));
770         QCOMPARE(str5.toInteger(), 123.0);
771
772         QJSValue str6 = QJSValue(&eng, QLatin1String("-456.5"));
773         QCOMPARE(str6.toInteger(), -456.0);
774     }
775     // V2 constructors
776     {
777         QJSValue number = QJSValue(123.0);
778         QCOMPARE(number.toInteger(), 123.0);
779
780         QJSValue number2 = QJSValue(qSNaN());
781         QCOMPARE(number2.toInteger(), 0.0);
782
783         QJSValue number3 = QJSValue(qInf());
784         QCOMPARE(qIsInf(number3.toInteger()), true);
785
786         QJSValue number4 = QJSValue(0.5);
787         QCOMPARE(number4.toInteger(), 0.0);
788
789         QJSValue number5 = QJSValue(123.5);
790         QCOMPARE(number5.toInteger(), 123.0);
791
792         QJSValue number6 = QJSValue(-456.5);
793         QCOMPARE(number6.toInteger(), -456.0);
794
795         QJSValue number7 = QJSValue(0x43211234);
796         QCOMPARE(number7.toInteger(), qreal(0x43211234));
797
798         QJSValue str = QJSValue("123.0");
799         QCOMPARE(str.toInteger(), 123.0);
800
801         QJSValue str2 = QJSValue("NaN");
802         QCOMPARE(str2.toInteger(), 0.0);
803
804         QJSValue str3 = QJSValue("Infinity");
805         QCOMPARE(qIsInf(str3.toInteger()), true);
806
807         QJSValue str4 = QJSValue("0.5");
808         QCOMPARE(str4.toInteger(), 0.0);
809
810         QJSValue str5 = QJSValue("123.5");
811         QCOMPARE(str5.toInteger(), 123.0);
812
813         QJSValue str6 = QJSValue("-456.5");
814         QCOMPARE(str6.toInteger(), -456.0);
815     }
816
817     QJSValue inv;
818     QCOMPARE(inv.toInteger(), 0.0);
819 }
820
821 void tst_QJSValue::toInt32()
822 {
823     QJSEngine eng;
824
825     {
826         QJSValue zer0 = QJSValue(&eng, 0.0);
827         QCOMPARE(zer0.toInt32(), 0);
828         QCOMPARE(qjsvalue_cast<qint32>(zer0), 0);
829
830         QJSValue number = QJSValue(&eng, 123.0);
831         QCOMPARE(number.toInt32(), 123);
832         QCOMPARE(qjsvalue_cast<qint32>(number), 123);
833
834         QJSValue number2 = QJSValue(&eng, qSNaN());
835         QCOMPARE(number2.toInt32(), 0);
836         QCOMPARE(qjsvalue_cast<qint32>(number2), 0);
837
838         QJSValue number3 = QJSValue(&eng, +qInf());
839         QCOMPARE(number3.toInt32(), 0);
840         QCOMPARE(qjsvalue_cast<qint32>(number3), 0);
841
842         QJSValue number3_2 = QJSValue(&eng, -qInf());
843         QCOMPARE(number3_2.toInt32(), 0);
844         QCOMPARE(qjsvalue_cast<qint32>(number3_2), 0);
845
846         QJSValue number4 = QJSValue(&eng, 0.5);
847         QCOMPARE(number4.toInt32(), 0);
848         QCOMPARE(qjsvalue_cast<qint32>(number4), 0);
849
850         QJSValue number5 = QJSValue(&eng, 123.5);
851         QCOMPARE(number5.toInt32(), 123);
852         QCOMPARE(qjsvalue_cast<qint32>(number5), 123);
853
854         QJSValue number6 = QJSValue(&eng, -456.5);
855         QCOMPARE(number6.toInt32(), -456);
856         QCOMPARE(qjsvalue_cast<qint32>(number6), -456);
857
858         QJSValue str = QJSValue(&eng, QLatin1String("123.0"));
859         QCOMPARE(str.toInt32(), 123);
860         QCOMPARE(qjsvalue_cast<qint32>(str), 123);
861
862         QJSValue str2 = QJSValue(&eng, QLatin1String("NaN"));
863         QCOMPARE(str2.toInt32(), 0);
864         QCOMPARE(qjsvalue_cast<qint32>(str2), 0);
865
866         QJSValue str3 = QJSValue(&eng, QLatin1String("Infinity"));
867         QCOMPARE(str3.toInt32(), 0);
868         QCOMPARE(qjsvalue_cast<qint32>(str3), 0);
869
870         QJSValue str3_2 = QJSValue(&eng, QLatin1String("-Infinity"));
871         QCOMPARE(str3_2.toInt32(), 0);
872         QCOMPARE(qjsvalue_cast<qint32>(str3_2), 0);
873
874         QJSValue str4 = QJSValue(&eng, QLatin1String("0.5"));
875         QCOMPARE(str4.toInt32(), 0);
876         QCOMPARE(qjsvalue_cast<qint32>(str4), 0);
877
878         QJSValue str5 = QJSValue(&eng, QLatin1String("123.5"));
879         QCOMPARE(str5.toInt32(), 123);
880         QCOMPARE(qjsvalue_cast<qint32>(str5), 123);
881
882         QJSValue str6 = QJSValue(&eng, QLatin1String("-456.5"));
883         QCOMPARE(str6.toInt32(), -456);
884         QCOMPARE(qjsvalue_cast<qint32>(str6), -456);
885     }
886     // V2 constructors
887     {
888         QJSValue zer0 = QJSValue(0.0);
889         QCOMPARE(zer0.toInt32(), 0);
890         QCOMPARE(qjsvalue_cast<qint32>(zer0), 0);
891
892         QJSValue number = QJSValue(123.0);
893         QCOMPARE(number.toInt32(), 123);
894         QCOMPARE(qjsvalue_cast<qint32>(number), 123);
895
896         QJSValue number2 = QJSValue(qSNaN());
897         QCOMPARE(number2.toInt32(), 0);
898         QCOMPARE(qjsvalue_cast<qint32>(number2), 0);
899
900         QJSValue number3 = QJSValue(+qInf());
901         QCOMPARE(number3.toInt32(), 0);
902         QCOMPARE(qjsvalue_cast<qint32>(number3), 0);
903
904         QJSValue number3_2 = QJSValue(-qInf());
905         QCOMPARE(number3_2.toInt32(), 0);
906         QCOMPARE(qjsvalue_cast<qint32>(number3_2), 0);
907
908         QJSValue number4 = QJSValue(0.5);
909         QCOMPARE(number4.toInt32(), 0);
910         QCOMPARE(qjsvalue_cast<qint32>(number4), 0);
911
912         QJSValue number5 = QJSValue(123.5);
913         QCOMPARE(number5.toInt32(), 123);
914         QCOMPARE(qjsvalue_cast<qint32>(number5), 123);
915
916         QJSValue number6 = QJSValue(-456.5);
917         QCOMPARE(number6.toInt32(), -456);
918         QCOMPARE(qjsvalue_cast<qint32>(number6), -456);
919
920         QJSValue number7 = QJSValue(0x43211234);
921         QCOMPARE(number7.toInt32(), 0x43211234);
922
923         QJSValue str = QJSValue("123.0");
924         QCOMPARE(str.toInt32(), 123);
925         QCOMPARE(qjsvalue_cast<qint32>(str), 123);
926
927         QJSValue str2 = QJSValue("NaN");
928         QCOMPARE(str2.toInt32(), 0);
929         QCOMPARE(qjsvalue_cast<qint32>(str2), 0);
930
931         QJSValue str3 = QJSValue("Infinity");
932         QCOMPARE(str3.toInt32(), 0);
933         QCOMPARE(qjsvalue_cast<qint32>(str3), 0);
934
935         QJSValue str3_2 = QJSValue("-Infinity");
936         QCOMPARE(str3_2.toInt32(), 0);
937         QCOMPARE(qjsvalue_cast<qint32>(str3_2), 0);
938
939         QJSValue str4 = QJSValue("0.5");
940         QCOMPARE(str4.toInt32(), 0);
941         QCOMPARE(qjsvalue_cast<qint32>(str4), 0);
942
943         QJSValue str5 = QJSValue("123.5");
944         QCOMPARE(str5.toInt32(), 123);
945         QCOMPARE(qjsvalue_cast<qint32>(str5), 123);
946
947         QJSValue str6 = QJSValue("-456.5");
948         QCOMPARE(str6.toInt32(), -456);
949         QCOMPARE(qjsvalue_cast<qint32>(str6), -456);
950     }
951
952     QJSValue inv;
953     QCOMPARE(inv.toInt32(), 0);
954     QCOMPARE(qjsvalue_cast<qint32>(inv), 0);
955 }
956
957 void tst_QJSValue::toUInt32()
958 {
959     QJSEngine eng;
960
961     {
962         QJSValue zer0 = QJSValue(&eng, 0.0);
963         QCOMPARE(zer0.toUInt32(), quint32(0));
964         QCOMPARE(qjsvalue_cast<quint32>(zer0), quint32(0));
965
966         QJSValue number = QJSValue(&eng, 123.0);
967         QCOMPARE(number.toUInt32(), quint32(123));
968         QCOMPARE(qjsvalue_cast<quint32>(number), quint32(123));
969
970         QJSValue number2 = QJSValue(&eng, qSNaN());
971         QCOMPARE(number2.toUInt32(), quint32(0));
972         QCOMPARE(qjsvalue_cast<quint32>(number2), quint32(0));
973
974         QJSValue number3 = QJSValue(&eng, +qInf());
975         QCOMPARE(number3.toUInt32(), quint32(0));
976         QCOMPARE(qjsvalue_cast<quint32>(number3), quint32(0));
977
978         QJSValue number3_2 = QJSValue(&eng, -qInf());
979         QCOMPARE(number3_2.toUInt32(), quint32(0));
980         QCOMPARE(qjsvalue_cast<quint32>(number3_2), quint32(0));
981
982         QJSValue number4 = QJSValue(&eng, 0.5);
983         QCOMPARE(number4.toUInt32(), quint32(0));
984
985         QJSValue number5 = QJSValue(&eng, 123.5);
986         QCOMPARE(number5.toUInt32(), quint32(123));
987
988         QJSValue number6 = QJSValue(&eng, -456.5);
989         QCOMPARE(number6.toUInt32(), quint32(-456));
990         QCOMPARE(qjsvalue_cast<quint32>(number6), quint32(-456));
991
992         QJSValue str = QJSValue(&eng, QLatin1String("123.0"));
993         QCOMPARE(str.toUInt32(), quint32(123));
994         QCOMPARE(qjsvalue_cast<quint32>(str), quint32(123));
995
996         QJSValue str2 = QJSValue(&eng, QLatin1String("NaN"));
997         QCOMPARE(str2.toUInt32(), quint32(0));
998         QCOMPARE(qjsvalue_cast<quint32>(str2), quint32(0));
999
1000         QJSValue str3 = QJSValue(&eng, QLatin1String("Infinity"));
1001         QCOMPARE(str3.toUInt32(), quint32(0));
1002         QCOMPARE(qjsvalue_cast<quint32>(str3), quint32(0));
1003
1004         QJSValue str3_2 = QJSValue(&eng, QLatin1String("-Infinity"));
1005         QCOMPARE(str3_2.toUInt32(), quint32(0));
1006         QCOMPARE(qjsvalue_cast<quint32>(str3_2), quint32(0));
1007
1008         QJSValue str4 = QJSValue(&eng, QLatin1String("0.5"));
1009         QCOMPARE(str4.toUInt32(), quint32(0));
1010         QCOMPARE(qjsvalue_cast<quint32>(str4), quint32(0));
1011
1012         QJSValue str5 = QJSValue(&eng, QLatin1String("123.5"));
1013         QCOMPARE(str5.toUInt32(), quint32(123));
1014         QCOMPARE(qjsvalue_cast<quint32>(str5), quint32(123));
1015
1016         QJSValue str6 = QJSValue(&eng, QLatin1String("-456.5"));
1017         QCOMPARE(str6.toUInt32(), quint32(-456));
1018         QCOMPARE(qjsvalue_cast<quint32>(str6), quint32(-456));
1019     }
1020     // V2 constructors
1021     {
1022         QJSValue zer0 = QJSValue(0.0);
1023         QCOMPARE(zer0.toUInt32(), quint32(0));
1024         QCOMPARE(qjsvalue_cast<quint32>(zer0), quint32(0));
1025
1026         QJSValue number = QJSValue(123.0);
1027         QCOMPARE(number.toUInt32(), quint32(123));
1028         QCOMPARE(qjsvalue_cast<quint32>(number), quint32(123));
1029
1030         QJSValue number2 = QJSValue(qSNaN());
1031         QCOMPARE(number2.toUInt32(), quint32(0));
1032         QCOMPARE(qjsvalue_cast<quint32>(number2), quint32(0));
1033
1034         QJSValue number3 = QJSValue(+qInf());
1035         QCOMPARE(number3.toUInt32(), quint32(0));
1036         QCOMPARE(qjsvalue_cast<quint32>(number3), quint32(0));
1037
1038         QJSValue number3_2 = QJSValue(-qInf());
1039         QCOMPARE(number3_2.toUInt32(), quint32(0));
1040         QCOMPARE(qjsvalue_cast<quint32>(number3_2), quint32(0));
1041
1042         QJSValue number4 = QJSValue(0.5);
1043         QCOMPARE(number4.toUInt32(), quint32(0));
1044
1045         QJSValue number5 = QJSValue(123.5);
1046         QCOMPARE(number5.toUInt32(), quint32(123));
1047
1048         QJSValue number6 = QJSValue(-456.5);
1049         QCOMPARE(number6.toUInt32(), quint32(-456));
1050         QCOMPARE(qjsvalue_cast<quint32>(number6), quint32(-456));
1051
1052         QJSValue number7 = QJSValue(0x43211234);
1053         QCOMPARE(number7.toUInt32(), quint32(0x43211234));
1054
1055         QJSValue str = QJSValue(QLatin1String("123.0"));
1056         QCOMPARE(str.toUInt32(), quint32(123));
1057         QCOMPARE(qjsvalue_cast<quint32>(str), quint32(123));
1058
1059         QJSValue str2 = QJSValue(QLatin1String("NaN"));
1060         QCOMPARE(str2.toUInt32(), quint32(0));
1061         QCOMPARE(qjsvalue_cast<quint32>(str2), quint32(0));
1062
1063         QJSValue str3 = QJSValue(QLatin1String("Infinity"));
1064         QCOMPARE(str3.toUInt32(), quint32(0));
1065         QCOMPARE(qjsvalue_cast<quint32>(str3), quint32(0));
1066
1067         QJSValue str3_2 = QJSValue(QLatin1String("-Infinity"));
1068         QCOMPARE(str3_2.toUInt32(), quint32(0));
1069         QCOMPARE(qjsvalue_cast<quint32>(str3_2), quint32(0));
1070
1071         QJSValue str4 = QJSValue(QLatin1String("0.5"));
1072         QCOMPARE(str4.toUInt32(), quint32(0));
1073         QCOMPARE(qjsvalue_cast<quint32>(str4), quint32(0));
1074
1075         QJSValue str5 = QJSValue(QLatin1String("123.5"));
1076         QCOMPARE(str5.toUInt32(), quint32(123));
1077         QCOMPARE(qjsvalue_cast<quint32>(str5), quint32(123));
1078
1079         QJSValue str6 = QJSValue(QLatin1String("-456.5"));
1080         QCOMPARE(str6.toUInt32(), quint32(-456));
1081         QCOMPARE(qjsvalue_cast<quint32>(str6), quint32(-456));
1082     }
1083
1084     QJSValue inv;
1085     QCOMPARE(inv.toUInt32(), quint32(0));
1086     QCOMPARE(qjsvalue_cast<quint32>(inv), quint32(0));
1087 }
1088
1089 void tst_QJSValue::toUInt16()
1090 {
1091     QJSEngine eng;
1092
1093     {
1094         QJSValue zer0 = QJSValue(&eng, 0.0);
1095         QCOMPARE(zer0.toUInt16(), quint16(0));
1096         QCOMPARE(qjsvalue_cast<quint16>(zer0), quint16(0));
1097
1098         QJSValue number = QJSValue(&eng, 123.0);
1099         QCOMPARE(number.toUInt16(), quint16(123));
1100         QCOMPARE(qjsvalue_cast<quint16>(number), quint16(123));
1101
1102         QJSValue number2 = QJSValue(&eng, qSNaN());
1103         QCOMPARE(number2.toUInt16(), quint16(0));
1104         QCOMPARE(qjsvalue_cast<quint16>(number2), quint16(0));
1105
1106         QJSValue number3 = QJSValue(&eng, +qInf());
1107         QCOMPARE(number3.toUInt16(), quint16(0));
1108         QCOMPARE(qjsvalue_cast<quint16>(number3), quint16(0));
1109
1110         QJSValue number3_2 = QJSValue(&eng, -qInf());
1111         QCOMPARE(number3_2.toUInt16(), quint16(0));
1112         QCOMPARE(qjsvalue_cast<quint16>(number3_2), quint16(0));
1113
1114         QJSValue number4 = QJSValue(&eng, 0.5);
1115         QCOMPARE(number4.toUInt16(), quint16(0));
1116
1117         QJSValue number5 = QJSValue(&eng, 123.5);
1118         QCOMPARE(number5.toUInt16(), quint16(123));
1119
1120         QJSValue number6 = QJSValue(&eng, -456.5);
1121         QCOMPARE(number6.toUInt16(), quint16(-456));
1122         QCOMPARE(qjsvalue_cast<quint16>(number6), quint16(-456));
1123
1124         QJSValue number7 = QJSValue(&eng, 0x10000);
1125         QCOMPARE(number7.toUInt16(), quint16(0));
1126         QCOMPARE(qjsvalue_cast<quint16>(number7), quint16(0));
1127
1128         QJSValue number8 = QJSValue(&eng, 0x10001);
1129         QCOMPARE(number8.toUInt16(), quint16(1));
1130         QCOMPARE(qjsvalue_cast<quint16>(number8), quint16(1));
1131
1132         QJSValue str = QJSValue(&eng, QLatin1String("123.0"));
1133         QCOMPARE(str.toUInt16(), quint16(123));
1134         QCOMPARE(qjsvalue_cast<quint16>(str), quint16(123));
1135
1136         QJSValue str2 = QJSValue(&eng, QLatin1String("NaN"));
1137         QCOMPARE(str2.toUInt16(), quint16(0));
1138         QCOMPARE(qjsvalue_cast<quint16>(str2), quint16(0));
1139
1140         QJSValue str3 = QJSValue(&eng, QLatin1String("Infinity"));
1141         QCOMPARE(str3.toUInt16(), quint16(0));
1142         QCOMPARE(qjsvalue_cast<quint16>(str3), quint16(0));
1143
1144         QJSValue str3_2 = QJSValue(&eng, QLatin1String("-Infinity"));
1145         QCOMPARE(str3_2.toUInt16(), quint16(0));
1146         QCOMPARE(qjsvalue_cast<quint16>(str3_2), quint16(0));
1147
1148         QJSValue str4 = QJSValue(&eng, QLatin1String("0.5"));
1149         QCOMPARE(str4.toUInt16(), quint16(0));
1150
1151         QJSValue str5 = QJSValue(&eng, QLatin1String("123.5"));
1152         QCOMPARE(str5.toUInt16(), quint16(123));
1153
1154         QJSValue str6 = QJSValue(&eng, QLatin1String("-456.5"));
1155         QCOMPARE(str6.toUInt16(), quint16(-456));
1156         QCOMPARE(qjsvalue_cast<quint16>(str6), quint16(-456));
1157
1158         QJSValue str7 = QJSValue(&eng, QLatin1String("0x10000"));
1159         QCOMPARE(str7.toUInt16(), quint16(0));
1160         QCOMPARE(qjsvalue_cast<quint16>(str7), quint16(0));
1161
1162         QJSValue str8 = QJSValue(&eng, QLatin1String("0x10001"));
1163         QCOMPARE(str8.toUInt16(), quint16(1));
1164         QCOMPARE(qjsvalue_cast<quint16>(str8), quint16(1));
1165     }
1166     // V2 constructors
1167     {
1168         QJSValue zer0 = QJSValue(0.0);
1169         QCOMPARE(zer0.toUInt16(), quint16(0));
1170         QCOMPARE(qjsvalue_cast<quint16>(zer0), quint16(0));
1171
1172         QJSValue number = QJSValue(123.0);
1173         QCOMPARE(number.toUInt16(), quint16(123));
1174         QCOMPARE(qjsvalue_cast<quint16>(number), quint16(123));
1175
1176         QJSValue number2 = QJSValue(qSNaN());
1177         QCOMPARE(number2.toUInt16(), quint16(0));
1178         QCOMPARE(qjsvalue_cast<quint16>(number2), quint16(0));
1179
1180         QJSValue number3 = QJSValue(+qInf());
1181         QCOMPARE(number3.toUInt16(), quint16(0));
1182         QCOMPARE(qjsvalue_cast<quint16>(number3), quint16(0));
1183
1184         QJSValue number3_2 = QJSValue(-qInf());
1185         QCOMPARE(number3_2.toUInt16(), quint16(0));
1186         QCOMPARE(qjsvalue_cast<quint16>(number3_2), quint16(0));
1187
1188         QJSValue number4 = QJSValue(0.5);
1189         QCOMPARE(number4.toUInt16(), quint16(0));
1190
1191         QJSValue number5 = QJSValue(123.5);
1192         QCOMPARE(number5.toUInt16(), quint16(123));
1193
1194         QJSValue number6 = QJSValue(-456.5);
1195         QCOMPARE(number6.toUInt16(), quint16(-456));
1196         QCOMPARE(qjsvalue_cast<quint16>(number6), quint16(-456));
1197
1198         QJSValue number7 = QJSValue(0x10000);
1199         QCOMPARE(number7.toUInt16(), quint16(0));
1200         QCOMPARE(qjsvalue_cast<quint16>(number7), quint16(0));
1201
1202         QJSValue number8 = QJSValue(0x10001);
1203         QCOMPARE(number8.toUInt16(), quint16(1));
1204         QCOMPARE(qjsvalue_cast<quint16>(number8), quint16(1));
1205
1206         QJSValue str = QJSValue(QLatin1String("123.0"));
1207         QCOMPARE(str.toUInt16(), quint16(123));
1208         QCOMPARE(qjsvalue_cast<quint16>(str), quint16(123));
1209
1210         QJSValue str2 = QJSValue(QLatin1String("NaN"));
1211         QCOMPARE(str2.toUInt16(), quint16(0));
1212         QCOMPARE(qjsvalue_cast<quint16>(str2), quint16(0));
1213
1214         QJSValue str3 = QJSValue(QLatin1String("Infinity"));
1215         QCOMPARE(str3.toUInt16(), quint16(0));
1216         QCOMPARE(qjsvalue_cast<quint16>(str3), quint16(0));
1217
1218         QJSValue str3_2 = QJSValue(QLatin1String("-Infinity"));
1219         QCOMPARE(str3_2.toUInt16(), quint16(0));
1220         QCOMPARE(qjsvalue_cast<quint16>(str3_2), quint16(0));
1221
1222         QJSValue str4 = QJSValue("0.5");
1223         QCOMPARE(str4.toUInt16(), quint16(0));
1224
1225         QJSValue str5 = QJSValue("123.5");
1226         QCOMPARE(str5.toUInt16(), quint16(123));
1227
1228         QJSValue str6 = QJSValue("-456.5");
1229         QCOMPARE(str6.toUInt16(), quint16(-456));
1230         QCOMPARE(qjsvalue_cast<quint16>(str6), quint16(-456));
1231
1232         QJSValue str7 = QJSValue("0x10000");
1233         QCOMPARE(str7.toUInt16(), quint16(0));
1234         QCOMPARE(qjsvalue_cast<quint16>(str7), quint16(0));
1235
1236         QJSValue str8 = QJSValue("0x10001");
1237         QCOMPARE(str8.toUInt16(), quint16(1));
1238         QCOMPARE(qjsvalue_cast<quint16>(str8), quint16(1));
1239     }
1240
1241     QJSValue inv;
1242     QCOMPARE(inv.toUInt16(), quint16(0));
1243     QCOMPARE(qjsvalue_cast<quint16>(inv), quint16(0));
1244 }
1245
1246 #if defined Q_CC_MSVC && _MSC_VER < 1300
1247 Q_DECLARE_METATYPE(QVariant)
1248 #endif
1249
1250 void tst_QJSValue::toVariant()
1251 {
1252     QJSEngine eng;
1253
1254     QJSValue undefined = eng.undefinedValue();
1255     QCOMPARE(undefined.toVariant(), QVariant());
1256     QCOMPARE(qjsvalue_cast<QVariant>(undefined), QVariant());
1257
1258     QJSValue null = eng.nullValue();
1259     QCOMPARE(null.toVariant(), QVariant());
1260     QCOMPARE(qjsvalue_cast<QVariant>(null), QVariant());
1261
1262     {
1263         QJSValue number = QJSValue(&eng, 123.0);
1264         QCOMPARE(number.toVariant(), QVariant(123.0));
1265         QCOMPARE(qjsvalue_cast<QVariant>(number), QVariant(123.0));
1266
1267         QJSValue intNumber = QJSValue(&eng, (qint32)123);
1268         QCOMPARE(intNumber.toVariant().type(), QVariant((qint32)123).type());
1269         QCOMPARE((qjsvalue_cast<QVariant>(number)).type(), QVariant((qint32)123).type());
1270
1271         QJSValue falskt = QJSValue(&eng, false);
1272         QCOMPARE(falskt.toVariant(), QVariant(false));
1273         QCOMPARE(qjsvalue_cast<QVariant>(falskt), QVariant(false));
1274
1275         QJSValue sant = QJSValue(&eng, true);
1276         QCOMPARE(sant.toVariant(), QVariant(true));
1277         QCOMPARE(qjsvalue_cast<QVariant>(sant), QVariant(true));
1278
1279         QJSValue str = QJSValue(&eng, QString("ciao"));
1280         QCOMPARE(str.toVariant(), QVariant(QString("ciao")));
1281         QCOMPARE(qjsvalue_cast<QVariant>(str), QVariant(QString("ciao")));
1282     }
1283
1284     QVariant var(QChar(0x007A));
1285     QJSValue opaque = eng.newVariant(var);
1286     QVERIFY(opaque.isVariant());
1287     QCOMPARE(opaque.toVariant(), var);
1288
1289     QJSValue object = eng.newObject();
1290     QCOMPARE(object.toVariant(), QVariant(QVariantMap()));
1291
1292     QJSValue qobject = eng.newQObject(this);
1293     {
1294         QVariant var = qobject.toVariant();
1295         QCOMPARE(var.userType(), int(QMetaType::QObjectStar));
1296         QCOMPARE(qVariantValue<QObject*>(var), (QObject *)this);
1297     }
1298
1299     {
1300         QDateTime dateTime = QDateTime(QDate(1980, 10, 4));
1301         QJSValue dateObject = eng.newDate(dateTime);
1302         QVariant var = dateObject.toVariant();
1303         QCOMPARE(var, QVariant(dateTime));
1304     }
1305
1306     {
1307         QRegExp rx = QRegExp("[0-9a-z]+", Qt::CaseSensitive, QRegExp::RegExp2);
1308         QJSValue rxObject = eng.newRegExp(rx);
1309         QVariant var = rxObject.toVariant();
1310         QCOMPARE(var, QVariant(rx));
1311     }
1312
1313     QJSValue inv;
1314     QCOMPARE(inv.toVariant(), QVariant());
1315     QCOMPARE(qjsvalue_cast<QVariant>(inv), QVariant());
1316
1317     // V2 constructors
1318     {
1319         QJSValue number = QJSValue(123.0);
1320         QCOMPARE(number.toVariant(), QVariant(123.0));
1321         QCOMPARE(qjsvalue_cast<QVariant>(number), QVariant(123.0));
1322
1323         QJSValue falskt = QJSValue(false);
1324         QCOMPARE(falskt.toVariant(), QVariant(false));
1325         QCOMPARE(qjsvalue_cast<QVariant>(falskt), QVariant(false));
1326
1327         QJSValue sant = QJSValue(true);
1328         QCOMPARE(sant.toVariant(), QVariant(true));
1329         QCOMPARE(qjsvalue_cast<QVariant>(sant), QVariant(true));
1330
1331         QJSValue str = QJSValue(QString("ciao"));
1332         QCOMPARE(str.toVariant(), QVariant(QString("ciao")));
1333         QCOMPARE(qjsvalue_cast<QVariant>(str), QVariant(QString("ciao")));
1334     }
1335
1336 #if 0 // FIXME: No automatic sequence conversion
1337     // array
1338     {
1339         QVariantList listIn;
1340         listIn << 123 << "hello";
1341         QJSValue array = qScriptValueFromValue(&eng, listIn);
1342         QVERIFY(array.isArray());
1343         QCOMPARE(array.property("length").toInt32(), 2);
1344         QVariant ret = array.toVariant();
1345         QCOMPARE(ret.type(), QVariant::List);
1346         QVariantList listOut = ret.toList();
1347         QCOMPARE(listOut.size(), listIn.size());
1348         for (int i = 0; i < listIn.size(); ++i)
1349             QVERIFY(listOut.at(i) == listIn.at(i));
1350         // round-trip conversion
1351         QJSValue array2 = qScriptValueFromValue(&eng, ret);
1352         QVERIFY(array2.isArray());
1353         QCOMPARE(array2.property("length").toInt32(), array.property("length").toInt32());
1354         for (int i = 0; i < array.property("length").toInt32(); ++i)
1355             QVERIFY(array2.property(i).strictlyEquals(array.property(i)));
1356     }
1357 #endif
1358 }
1359
1360 void tst_QJSValue::toQObject_nonQObject_data()
1361 {
1362     newEngine();
1363     QTest::addColumn<QJSValue>("value");
1364
1365     QTest::newRow("invalid") << QJSValue();
1366     QTest::newRow("bool(false)") << QJSValue(false);
1367     QTest::newRow("bool(true)") << QJSValue(true);
1368     QTest::newRow("int") << QJSValue(123);
1369     QTest::newRow("string") << QJSValue(QString::fromLatin1("ciao"));
1370     QTest::newRow("undefined") << QJSValue(QJSValue::UndefinedValue);
1371     QTest::newRow("null") << QJSValue(QJSValue::NullValue);
1372
1373     QTest::newRow("bool bound(false)") << QJSValue(engine, false);
1374     QTest::newRow("bool bound(true)") << QJSValue(engine, true);
1375     QTest::newRow("int bound") << QJSValue(engine, 123);
1376     QTest::newRow("string bound") << QJSValue(engine, QString::fromLatin1("ciao"));
1377     QTest::newRow("undefined bound") << engine->undefinedValue();
1378     QTest::newRow("null bound") << engine->nullValue();
1379     QTest::newRow("object") << engine->newObject();
1380     QTest::newRow("array") << engine->newArray();
1381     QTest::newRow("date") << engine->newDate(124);
1382     QTest::newRow("variant(12345)") << engine->newVariant(12345);
1383     QTest::newRow("variant((QObject*)0)") << engine->newVariant(qVariantFromValue((QObject*)0));
1384     QTest::newRow("newQObject(0)") << engine->newQObject(0);
1385 }
1386
1387
1388 void tst_QJSValue::toQObject_nonQObject()
1389 {
1390     QFETCH(QJSValue, value);
1391     QCOMPARE(value.toQObject(), (QObject *)0);
1392     QCOMPARE(qjsvalue_cast<QObject*>(value), (QObject *)0);
1393 }
1394
1395 // unfortunately, this is necessary in order to do qscriptvalue_cast<QPushButton*>(...)
1396 Q_DECLARE_METATYPE(QPushButton*);
1397
1398 void tst_QJSValue::toQObject()
1399 {
1400     QJSEngine eng;
1401
1402     QJSValue qobject = eng.newQObject(this);
1403     QCOMPARE(qobject.toQObject(), (QObject *)this);
1404     QCOMPARE(qjsvalue_cast<QObject*>(qobject), (QObject *)this);
1405     QCOMPARE(qjsvalue_cast<QWidget*>(qobject), (QWidget *)0);
1406
1407     QWidget widget;
1408     QJSValue qwidget = eng.newQObject(&widget);
1409     QCOMPARE(qwidget.toQObject(), (QObject *)&widget);
1410     QCOMPARE(qjsvalue_cast<QObject*>(qwidget), (QObject *)&widget);
1411     QCOMPARE(qjsvalue_cast<QWidget*>(qwidget), &widget);
1412
1413     QPushButton button;
1414     QJSValue qbutton = eng.newQObject(&button);
1415     QCOMPARE(qbutton.toQObject(), (QObject *)&button);
1416     QCOMPARE(qjsvalue_cast<QObject*>(qbutton), (QObject *)&button);
1417     QCOMPARE(qjsvalue_cast<QWidget*>(qbutton), (QWidget *)&button);
1418     QCOMPARE(qjsvalue_cast<QPushButton*>(qbutton), &button);
1419
1420     // wrapping a QObject* as variant
1421     QJSValue variant = eng.newVariant(qVariantFromValue((QObject*)&button));
1422     QCOMPARE(variant.toQObject(), (QObject*)&button);
1423     QCOMPARE(qjsvalue_cast<QObject*>(variant), (QObject*)&button);
1424     QCOMPARE(qjsvalue_cast<QWidget*>(variant), (QWidget*)&button);
1425     QCOMPARE(qjsvalue_cast<QPushButton*>(variant), &button);
1426
1427     QJSValue variant2 = eng.newVariant(qVariantFromValue((QWidget*)&button));
1428     QCOMPARE(variant2.toQObject(), (QObject*)&button);
1429     QCOMPARE(qjsvalue_cast<QObject*>(variant2), (QObject*)&button);
1430     QCOMPARE(qjsvalue_cast<QWidget*>(variant2), (QWidget*)&button);
1431     QCOMPARE(qjsvalue_cast<QPushButton*>(variant2), &button);
1432
1433     QJSValue variant3 = eng.newVariant(qVariantFromValue(&button));
1434     QCOMPARE(variant3.toQObject(), (QObject*)0);
1435     QCOMPARE(qjsvalue_cast<QObject*>(variant3), (QObject*)0);
1436     QCOMPARE(qjsvalue_cast<QWidget*>(variant3), (QWidget*)0);
1437     QCOMPARE(qjsvalue_cast<QPushButton*>(variant3), &button);
1438 }
1439
1440 void tst_QJSValue::toObject()
1441 {
1442     QJSEngine eng;
1443
1444     QJSValue undefined = eng.undefinedValue();
1445     QCOMPARE(undefined.toObject().isValid(), false);
1446     QVERIFY(undefined.isUndefined());
1447
1448     QJSValue null = eng.nullValue();
1449     QCOMPARE(null.toObject().isValid(), false);
1450     QVERIFY(null.isNull());
1451
1452     {
1453         QJSValue falskt = QJSValue(&eng, false);
1454         {
1455             QJSValue tmp = falskt.toObject();
1456             QCOMPARE(tmp.isObject(), true);
1457             QCOMPARE(tmp.toNumber(), falskt.toNumber());
1458         }
1459         QVERIFY(falskt.isBool());
1460
1461         QJSValue sant = QJSValue(&eng, true);
1462         {
1463             QJSValue tmp = sant.toObject();
1464             QCOMPARE(tmp.isObject(), true);
1465             QCOMPARE(tmp.toNumber(), sant.toNumber());
1466         }
1467         QVERIFY(sant.isBool());
1468
1469         QJSValue number = QJSValue(&eng, 123.0);
1470         {
1471             QJSValue tmp = number.toObject();
1472             QCOMPARE(tmp.isObject(), true);
1473             QCOMPARE(tmp.toNumber(), number.toNumber());
1474         }
1475         QVERIFY(number.isNumber());
1476
1477         QJSValue str = QJSValue(&eng, QString("ciao"));
1478         {
1479             QJSValue tmp = str.toObject();
1480             QCOMPARE(tmp.isObject(), true);
1481             QCOMPARE(tmp.toString(), str.toString());
1482         }
1483         QVERIFY(str.isString());
1484     }
1485
1486     QJSValue object = eng.newObject();
1487     {
1488         QJSValue tmp = object.toObject();
1489         QCOMPARE(tmp.isObject(), true);
1490     }
1491
1492     QJSValue qobject = eng.newQObject(this);
1493     QCOMPARE(qobject.toObject().isValid(), true);
1494
1495     QJSValue inv;
1496     QCOMPARE(inv.toObject().isValid(), false);
1497
1498     // V2 constructors: in this case, you have to use QScriptEngine::toObject()
1499     {
1500         QJSValue undefined = QJSValue(QJSValue::UndefinedValue);
1501         QVERIFY(!undefined.toObject().isValid());
1502         QVERIFY(!eng.toObject(undefined).isValid());
1503         QVERIFY(undefined.isUndefined());
1504
1505         QJSValue null = QJSValue(QJSValue::NullValue);
1506         QVERIFY(!null.toObject().isValid());
1507         QVERIFY(!eng.toObject(null).isValid());
1508         QVERIFY(null.isNull());
1509
1510         QJSValue falskt = QJSValue(false);
1511         QVERIFY(!falskt.toObject().isValid());
1512         {
1513             QJSValue tmp = eng.toObject(falskt);
1514             QVERIFY(tmp.isObject());
1515             QVERIFY(tmp.toBool());
1516         }
1517         QVERIFY(falskt.isBool());
1518
1519         QJSValue sant = QJSValue(true);
1520         QVERIFY(!sant.toObject().isValid());
1521         {
1522             QJSValue tmp = eng.toObject(sant);
1523             QVERIFY(tmp.isObject());
1524             QVERIFY(tmp.toBool());
1525         }
1526         QVERIFY(sant.isBool());
1527
1528         QJSValue number = QJSValue(123.0);
1529         QVERIFY(!number.toObject().isValid());
1530         {
1531             QJSValue tmp = eng.toObject(number);
1532             QVERIFY(tmp.isObject());
1533             QCOMPARE(tmp.toInt32(), number.toInt32());
1534         }
1535         QVERIFY(number.isNumber());
1536
1537         QJSValue str = QJSValue(QString::fromLatin1("ciao"));
1538         QVERIFY(!str.toObject().isValid());
1539         {
1540             QJSValue tmp = eng.toObject(str);
1541             QVERIFY(tmp.isObject());
1542             QCOMPARE(tmp.toString(), QString::fromLatin1("ciao"));
1543         }
1544         QVERIFY(str.isString());
1545     }
1546 }
1547
1548 void tst_QJSValue::toDateTime()
1549 {
1550     QJSEngine eng;
1551     QDateTime dt = eng.evaluate("new Date(0)").toDateTime();
1552     QVERIFY(dt.isValid());
1553     QCOMPARE(dt.timeSpec(), Qt::LocalTime);
1554     QCOMPARE(dt.toUTC(), QDateTime(QDate(1970, 1, 1), QTime(0, 0, 0), Qt::UTC));
1555
1556     QVERIFY(!eng.evaluate("[]").toDateTime().isValid());
1557     QVERIFY(!eng.evaluate("{}").toDateTime().isValid());
1558     QVERIFY(!eng.globalObject().toDateTime().isValid());
1559     QVERIFY(!QJSValue().toDateTime().isValid());
1560     QVERIFY(!QJSValue(123).toDateTime().isValid());
1561     QVERIFY(!QJSValue(false).toDateTime().isValid());
1562     QVERIFY(!eng.nullValue().toDateTime().isValid());
1563     QVERIFY(!eng.undefinedValue().toDateTime().isValid());
1564 }
1565
1566 void tst_QJSValue::toRegExp()
1567 {
1568     QJSEngine eng;
1569     {
1570         QRegExp rx = eng.evaluate("/foo/").toRegExp();
1571         QVERIFY(rx.isValid());
1572         QCOMPARE(rx.patternSyntax(), QRegExp::RegExp2);
1573         QCOMPARE(rx.pattern(), QString::fromLatin1("foo"));
1574         QCOMPARE(rx.caseSensitivity(), Qt::CaseSensitive);
1575         QVERIFY(!rx.isMinimal());
1576     }
1577     {
1578         QRegExp rx = eng.evaluate("/bar/gi").toRegExp();
1579         QVERIFY(rx.isValid());
1580         QCOMPARE(rx.patternSyntax(), QRegExp::RegExp2);
1581         QCOMPARE(rx.pattern(), QString::fromLatin1("bar"));
1582         QCOMPARE(rx.caseSensitivity(), Qt::CaseInsensitive);
1583         QVERIFY(!rx.isMinimal());
1584     }
1585
1586     QVERIFY(eng.evaluate("[]").toRegExp().isEmpty());
1587     QVERIFY(eng.evaluate("{}").toRegExp().isEmpty());
1588     QVERIFY(eng.globalObject().toRegExp().isEmpty());
1589     QVERIFY(QJSValue().toRegExp().isEmpty());
1590     QVERIFY(QJSValue(123).toRegExp().isEmpty());
1591     QVERIFY(QJSValue(false).toRegExp().isEmpty());
1592     QVERIFY(eng.nullValue().toRegExp().isEmpty());
1593     QVERIFY(eng.undefinedValue().toRegExp().isEmpty());
1594 }
1595
1596 void tst_QJSValue::instanceOf_twoEngines()
1597 {
1598     QJSEngine eng;
1599     QJSValue obj = eng.newObject();
1600     QJSEngine otherEngine;
1601     QTest::ignoreMessage(QtWarningMsg, "QJSValue::instanceof: cannot perform operation on a value created in a different engine");
1602     QCOMPARE(obj.instanceOf(otherEngine.globalObject().property("Object")), false);
1603 }
1604
1605 void tst_QJSValue::instanceOf()
1606 {
1607     QJSEngine eng;
1608     QJSValue obj = eng.newObject();
1609     QCOMPARE(obj.instanceOf(eng.evaluate("Object.prototype")), false);
1610     QCOMPARE(obj.instanceOf(eng.evaluate("Array.prototype")), false);
1611     QCOMPARE(obj.instanceOf(eng.evaluate("Function.prototype")), false);
1612     QCOMPARE(obj.instanceOf(eng.evaluate("QObject.prototype")), false);
1613     QCOMPARE(obj.instanceOf(QJSValue(&eng, 123)), false);
1614     QCOMPARE(obj.instanceOf(eng.undefinedValue()), false);
1615     QCOMPARE(obj.instanceOf(eng.nullValue()), false);
1616     QCOMPARE(obj.instanceOf(QJSValue()), false);
1617
1618     QCOMPARE(obj.instanceOf(eng.evaluate("Object")), true);
1619     QCOMPARE(obj.instanceOf(eng.evaluate("Array")), false);
1620     QCOMPARE(obj.instanceOf(eng.evaluate("Function")), false);
1621     QCOMPARE(obj.instanceOf(eng.evaluate("QObject")), false);
1622
1623     QJSValue arr = eng.newArray();
1624     QVERIFY(arr.isArray());
1625     QCOMPARE(arr.instanceOf(eng.evaluate("Object.prototype")), false);
1626     QCOMPARE(arr.instanceOf(eng.evaluate("Array.prototype")), false);
1627     QCOMPARE(arr.instanceOf(eng.evaluate("Function.prototype")), false);
1628     QCOMPARE(arr.instanceOf(eng.evaluate("QObject.prototype")), false);
1629     QCOMPARE(arr.instanceOf(eng.evaluate("Object")), true);
1630     QCOMPARE(arr.instanceOf(eng.evaluate("Array")), true);
1631     QCOMPARE(arr.instanceOf(eng.evaluate("Function")), false);
1632     QCOMPARE(arr.instanceOf(eng.evaluate("QObject")), false);
1633
1634     QCOMPARE(QJSValue().instanceOf(arr), false);
1635 }
1636
1637 void tst_QJSValue::isArray_data()
1638 {
1639     newEngine();
1640
1641     QTest::addColumn<QJSValue>("value");
1642     QTest::addColumn<bool>("array");
1643
1644     QTest::newRow("[]") << engine->evaluate("[]") << true;
1645     QTest::newRow("{}") << engine->evaluate("{}") << false;
1646     QTest::newRow("globalObject") << engine->globalObject() << false;
1647     QTest::newRow("invalid") << QJSValue() << false;
1648     QTest::newRow("number") << QJSValue(123) << false;
1649     QTest::newRow("bool") << QJSValue(false) << false;
1650     QTest::newRow("null") << engine->nullValue() << false;
1651     QTest::newRow("undefined") << engine->undefinedValue() << false;
1652 }
1653
1654 void tst_QJSValue::isArray()
1655 {
1656     QFETCH(QJSValue, value);
1657     QFETCH(bool, array);
1658
1659     QCOMPARE(value.isArray(), array);
1660 }
1661
1662 void tst_QJSValue::isDate_data()
1663 {
1664     newEngine();
1665
1666     QTest::addColumn<QJSValue>("value");
1667     QTest::addColumn<bool>("date");
1668
1669     QTest::newRow("date") << engine->evaluate("new Date()") << true;
1670     QTest::newRow("[]") << engine->evaluate("[]") << false;
1671     QTest::newRow("{}") << engine->evaluate("{}") << false;
1672     QTest::newRow("globalObject") << engine->globalObject() << false;
1673     QTest::newRow("invalid") << QJSValue() << false;
1674     QTest::newRow("number") << QJSValue(123) << false;
1675     QTest::newRow("bool") << QJSValue(false) << false;
1676     QTest::newRow("null") << engine->nullValue() << false;
1677     QTest::newRow("undefined") << engine->undefinedValue() << false;
1678 }
1679
1680 void tst_QJSValue::isDate()
1681 {
1682     QFETCH(QJSValue, value);
1683     QFETCH(bool, date);
1684
1685     QCOMPARE(value.isDate(), date);
1686 }
1687
1688 void tst_QJSValue::isError_propertiesOfGlobalObject()
1689 {
1690     QStringList errors;
1691     errors << "Error"
1692            << "EvalError"
1693            << "RangeError"
1694            << "ReferenceError"
1695            << "SyntaxError"
1696            << "TypeError"
1697            << "URIError";
1698     QJSEngine eng;
1699     for (int i = 0; i < errors.size(); ++i) {
1700         QJSValue ctor = eng.globalObject().property(errors.at(i));
1701         QVERIFY(ctor.isFunction());
1702         QVERIFY(ctor.property("prototype").isError());
1703     }
1704 }
1705
1706 void tst_QJSValue::isError_data()
1707 {
1708     newEngine();
1709
1710     QTest::addColumn<QJSValue>("value");
1711     QTest::addColumn<bool>("error");
1712
1713     QTest::newRow("syntax error") << engine->evaluate("%fsdg's") << true;
1714     QTest::newRow("[]") << engine->evaluate("[]") << false;
1715     QTest::newRow("{}") << engine->evaluate("{}") << false;
1716     QTest::newRow("globalObject") << engine->globalObject() << false;
1717     QTest::newRow("invalid") << QJSValue() << false;
1718     QTest::newRow("number") << QJSValue(123) << false;
1719     QTest::newRow("bool") << QJSValue(false) << false;
1720     QTest::newRow("null") << engine->nullValue() << false;
1721     QTest::newRow("undefined") << engine->undefinedValue() << false;
1722     QTest::newRow("newObject") << engine->newObject() << false;
1723     QTest::newRow("new Object") << engine->evaluate("new Object()") << false;
1724 }
1725
1726 void tst_QJSValue::isError()
1727 {
1728     QFETCH(QJSValue, value);
1729     QFETCH(bool, error);
1730
1731     QCOMPARE(value.isError(), error);
1732 }
1733
1734 void tst_QJSValue::isRegExp_data()
1735 {
1736     newEngine();
1737
1738     QTest::addColumn<QJSValue>("value");
1739     QTest::addColumn<bool>("regexp");
1740
1741     QTest::newRow("/foo/") << engine->evaluate("/foo/") << true;
1742     QTest::newRow("[]") << engine->evaluate("[]") << false;
1743     QTest::newRow("{}") << engine->evaluate("{}") << false;
1744     QTest::newRow("globalObject") << engine->globalObject() << false;
1745     QTest::newRow("invalid") << QJSValue() << false;
1746     QTest::newRow("number") << QJSValue(123) << false;
1747     QTest::newRow("bool") << QJSValue(false) << false;
1748     QTest::newRow("null") << engine->nullValue() << false;
1749     QTest::newRow("undefined") << engine->undefinedValue() << false;
1750 }
1751
1752 void tst_QJSValue::isRegExp()
1753 {
1754     QFETCH(QJSValue, value);
1755     QFETCH(bool, regexp);
1756
1757     QCOMPARE(value.isRegExp(), regexp);
1758 }
1759
1760 #if 0 // FIXME: No c-style callbacks currently
1761 static QJSValue getter(QScriptContext *ctx, QScriptEngine *)
1762 {
1763     return ctx->thisObject().property("x");
1764 }
1765
1766 static QJSValue setter(QScriptContext *ctx, QScriptEngine *)
1767 {
1768     ctx->thisObject().setProperty("x", ctx->argument(0));
1769     return ctx->argument(0);
1770 }
1771
1772 static QJSValue getterSetter(QScriptContext *ctx, QScriptEngine *)
1773 {
1774     if (ctx->argumentCount() > 0)
1775         ctx->thisObject().setProperty("x", ctx->argument(0));
1776     return ctx->thisObject().property("x");
1777 }
1778
1779 static QJSValue getterSetterThrowingError(QScriptContext *ctx, QScriptEngine *)
1780 {
1781     if (ctx->argumentCount() > 0)
1782         return ctx->throwError("set foo");
1783     else
1784         return ctx->throwError("get foo");
1785 }
1786
1787 static QJSValue getSet__proto__(QScriptContext *ctx, QScriptEngine *)
1788 {
1789     if (ctx->argumentCount() > 0)
1790         ctx->callee().setProperty("value", ctx->argument(0));
1791     return ctx->callee().property("value");
1792 }
1793 #endif
1794
1795 void tst_QJSValue::getSetProperty_HooliganTask162051()
1796 {
1797     QJSEngine eng;
1798     // task 162051 -- detecting whether the property is an array index or not
1799     QVERIFY(eng.evaluate("a = []; a['00'] = 123; a['00']").strictlyEquals(QJSValue(&eng, 123)));
1800     QVERIFY(eng.evaluate("a.length").strictlyEquals(QJSValue(&eng, 0)));
1801     QVERIFY(eng.evaluate("a.hasOwnProperty('00')").strictlyEquals(QJSValue(&eng, true)));
1802     QVERIFY(eng.evaluate("a.hasOwnProperty('0')").strictlyEquals(QJSValue(&eng, false)));
1803     QVERIFY(eng.evaluate("a[0]").isUndefined());
1804     QVERIFY(eng.evaluate("a[0.5] = 456; a[0.5]").strictlyEquals(QJSValue(&eng, 456)));
1805     QVERIFY(eng.evaluate("a.length").strictlyEquals(QJSValue(&eng, 0)));
1806     QVERIFY(eng.evaluate("a.hasOwnProperty('0.5')").strictlyEquals(QJSValue(&eng, true)));
1807     QVERIFY(eng.evaluate("a[0]").isUndefined());
1808     QVERIFY(eng.evaluate("a[0] = 789; a[0]").strictlyEquals(QJSValue(&eng, 789)));
1809     QVERIFY(eng.evaluate("a.length").strictlyEquals(QJSValue(&eng, 1)));
1810 }
1811
1812 void tst_QJSValue::getSetProperty_HooliganTask183072()
1813 {
1814     QJSEngine eng;
1815     // task 183072 -- 0x800000000 is not an array index
1816     eng.evaluate("a = []; a[0x800000000] = 123");
1817     QVERIFY(eng.evaluate("a.length").strictlyEquals(QJSValue(&eng, 0)));
1818     QVERIFY(eng.evaluate("a[0]").isUndefined());
1819     QVERIFY(eng.evaluate("a[0x800000000]").strictlyEquals(QJSValue(&eng, 123)));
1820 }
1821
1822 void tst_QJSValue::getSetProperty_propertyRemoval()
1823 {
1824     // test property removal (setProperty(QJSValue()))
1825     QJSEngine eng;
1826     QJSValue object = eng.newObject();
1827     QJSValue str = QJSValue(&eng, QLatin1String("bar"));
1828     QJSValue num = QJSValue(&eng, 123.0);
1829
1830     object.setProperty("foo", num);
1831     QCOMPARE(object.property("foo").strictlyEquals(num), true);
1832     object.setProperty("bar", str);
1833     QCOMPARE(object.property("bar").strictlyEquals(str), true);
1834     object.setProperty("foo", QJSValue());
1835     QCOMPARE(object.property("foo").isValid(), false);
1836     QCOMPARE(object.property("bar").strictlyEquals(str), true);
1837     object.setProperty("foo", num);
1838     QCOMPARE(object.property("foo").strictlyEquals(num), true);
1839     QCOMPARE(object.property("bar").strictlyEquals(str), true);
1840     object.setProperty("bar", QJSValue());
1841     QCOMPARE(object.property("bar").isValid(), false);
1842     QCOMPARE(object.property("foo").strictlyEquals(num), true);
1843     object.setProperty("foo", QJSValue());
1844     object.setProperty("foo", QJSValue());
1845
1846     eng.globalObject().setProperty("object3", object);
1847     QCOMPARE(eng.evaluate("object3.hasOwnProperty('foo')")
1848              .strictlyEquals(QJSValue(&eng, false)), true);
1849     object.setProperty("foo", num);
1850     QCOMPARE(eng.evaluate("object3.hasOwnProperty('foo')")
1851              .strictlyEquals(QJSValue(&eng, true)), true);
1852     eng.globalObject().setProperty("object3", QJSValue());
1853     QCOMPARE(eng.evaluate("this.hasOwnProperty('object3')")
1854              .strictlyEquals(QJSValue(&eng, false)), true);
1855 }
1856
1857 void tst_QJSValue::getSetProperty_resolveMode()
1858 {
1859     // test ResolveMode
1860     QJSEngine eng;
1861     QJSValue object = eng.newObject();
1862     QJSValue prototype = eng.newObject();
1863     object.setPrototype(prototype);
1864     QJSValue num2 = QJSValue(&eng, 456.0);
1865     prototype.setProperty("propertyInPrototype", num2);
1866     // default is ResolvePrototype
1867     QCOMPARE(object.property("propertyInPrototype")
1868              .strictlyEquals(num2), true);
1869 #if 0 // FIXME: ResolveFlags removed from API
1870     QCOMPARE(object.property("propertyInPrototype", QJSValue::ResolvePrototype)
1871              .strictlyEquals(num2), true);
1872     QCOMPARE(object.property("propertyInPrototype", QJSValue::ResolveLocal)
1873              .isValid(), false);
1874     QCOMPARE(object.property("propertyInPrototype", QJSValue::ResolveScope)
1875              .strictlyEquals(num2), false);
1876     QCOMPARE(object.property("propertyInPrototype", QJSValue::ResolveFull)
1877              .strictlyEquals(num2), true);
1878 #endif
1879 }
1880
1881 void tst_QJSValue::getSetProperty_twoEngines()
1882 {
1883     QJSEngine engine;
1884     QJSValue object = engine.newObject();
1885
1886     QJSEngine otherEngine;
1887     QJSValue otherNum = QJSValue(&otherEngine, 123);
1888     QTest::ignoreMessage(QtWarningMsg, "QJSValue::setProperty(oof) failed: cannot set value created in a different engine");
1889     object.setProperty("oof", otherNum);
1890     QCOMPARE(object.property("oof").isValid(), false);
1891 }
1892
1893
1894 void tst_QJSValue::getSetProperty_gettersAndSetters()
1895 {
1896 #if 0 // FIXME: No setters/getters right now
1897     QScriptEngine eng;
1898     QJSValue str = QJSValue(&eng, QLatin1String("bar"));
1899     QJSValue num = QJSValue(&eng, 123.0);
1900     QJSValue object = eng.newObject();
1901     for (int x = 0; x < 2; ++x) {
1902         object.setProperty("foo", QJSValue());
1903         // getter() returns this.x
1904         object.setProperty("foo", eng.newFunction(getter),
1905                             QJSValue::PropertyGetter | QJSValue::UserRange);
1906         QCOMPARE(object.propertyFlags("foo") & ~QJSValue::UserRange,
1907                  QJSValue::PropertyGetter );
1908
1909         QEXPECT_FAIL("", "QTBUG-17615: User-range flags are not retained for getter/setter properties", Continue);
1910         QCOMPARE(object.propertyFlags("foo"),
1911                  QJSValue::PropertyGetter | QJSValue::UserRange);
1912         object.setProperty("x", num);
1913         QCOMPARE(object.property("foo").strictlyEquals(num), true);
1914
1915         // setter() sets this.x
1916         object.setProperty("foo", eng.newFunction(setter),
1917                             QJSValue::PropertySetter);
1918         QCOMPARE(object.propertyFlags("foo") & ~QJSValue::UserRange,
1919                  QJSValue::PropertySetter | QJSValue::PropertyGetter);
1920
1921         QCOMPARE(object.propertyFlags("foo"),
1922                  QJSValue::PropertySetter | QJSValue::PropertyGetter);
1923         object.setProperty("foo", str);
1924         QCOMPARE(object.property("x").strictlyEquals(str), true);
1925         QCOMPARE(object.property("foo").strictlyEquals(str), true);
1926
1927         // kill the getter
1928         object.setProperty("foo", QJSValue(), QJSValue::PropertyGetter);
1929         QVERIFY(!(object.propertyFlags("foo") & QJSValue::PropertyGetter));
1930         QVERIFY(object.propertyFlags("foo") & QJSValue::PropertySetter);
1931         QCOMPARE(object.property("foo").isUndefined(), true);
1932
1933         // setter should still work
1934         object.setProperty("foo", num);
1935         QCOMPARE(object.property("x").strictlyEquals(num), true);
1936
1937         // kill the setter too
1938         object.setProperty("foo", QJSValue(), QJSValue::PropertySetter);
1939         QVERIFY(!(object.propertyFlags("foo") & QJSValue::PropertySetter));
1940         // now foo is just a regular property
1941         object.setProperty("foo", str);
1942         QCOMPARE(object.property("x").strictlyEquals(num), true);
1943         QCOMPARE(object.property("foo").strictlyEquals(str), true);
1944     }
1945
1946     for (int x = 0; x < 2; ++x) {
1947         object.setProperty("foo", QJSValue());
1948         // setter() sets this.x
1949         object.setProperty("foo", eng.newFunction(setter), QJSValue::PropertySetter);
1950         object.setProperty("foo", str);
1951         QCOMPARE(object.property("x").strictlyEquals(str), true);
1952         QCOMPARE(object.property("foo").isUndefined(), true);
1953
1954         // getter() returns this.x
1955         object.setProperty("foo", eng.newFunction(getter), QJSValue::PropertyGetter);
1956         object.setProperty("x", num);
1957         QCOMPARE(object.property("foo").strictlyEquals(num), true);
1958
1959         // kill the setter
1960         object.setProperty("foo", QJSValue(), QJSValue::PropertySetter);
1961         object.setProperty("foo", str);
1962
1963         // getter should still work
1964         QCOMPARE(object.property("foo").strictlyEquals(num), true);
1965
1966         // kill the getter too
1967         object.setProperty("foo", QJSValue(), QJSValue::PropertyGetter);
1968         // now foo is just a regular property
1969         object.setProperty("foo", str);
1970         QCOMPARE(object.property("x").strictlyEquals(num), true);
1971         QCOMPARE(object.property("foo").strictlyEquals(str), true);
1972     }
1973
1974     // use a single function as both getter and setter
1975     object.setProperty("foo", QJSValue());
1976     object.setProperty("foo", eng.newFunction(getterSetter),
1977                         QJSValue::PropertyGetter | QJSValue::PropertySetter);
1978     QCOMPARE(object.propertyFlags("foo"),
1979              QJSValue::PropertyGetter | QJSValue::PropertySetter);
1980     object.setProperty("x", num);
1981     QCOMPARE(object.property("foo").strictlyEquals(num), true);
1982
1983     // killing the getter will preserve the setter, even though they are the same function
1984     object.setProperty("foo", QJSValue(), QJSValue::PropertyGetter);
1985     QVERIFY(object.propertyFlags("foo") & QJSValue::PropertySetter);
1986     QCOMPARE(object.property("foo").isUndefined(), true);
1987 #endif
1988 }
1989
1990 void tst_QJSValue::getSetProperty_gettersAndSettersThrowErrorNative()
1991 {
1992 #if 0 // FIXME: No setters/getters right now
1993     // getter/setter that throws an error
1994     QScriptEngine eng;
1995     QJSValue str = QJSValue(&eng, "bar");
1996     QJSValue object = eng.newObject();
1997
1998     object.setProperty("foo", eng.newFunction(getterSetterThrowingError),
1999                         QJSValue::PropertyGetter | QJSValue::PropertySetter);
2000     QVERIFY(!eng.hasUncaughtException());
2001     QJSValue ret = object.property("foo");
2002     QVERIFY(ret.isError());
2003     QVERIFY(eng.hasUncaughtException());
2004     QVERIFY(ret.strictlyEquals(eng.uncaughtException()));
2005     QCOMPARE(ret.toString(), QLatin1String("Error: get foo"));
2006     eng.evaluate("Object"); // clear exception state...
2007     QVERIFY(!eng.hasUncaughtException());
2008     object.setProperty("foo", str);
2009     QVERIFY(eng.hasUncaughtException());
2010     QCOMPARE(eng.uncaughtException().toString(), QLatin1String("Error: set foo"));
2011 #endif
2012 }
2013
2014 void tst_QJSValue::getSetProperty_gettersAndSettersThrowErrorJS()
2015 {
2016     // getter/setter that throws an error (from js function)
2017     QJSEngine eng;
2018     QJSValue str = QJSValue(&eng, QLatin1String("bar"));
2019
2020     eng.evaluate("o = new Object; "
2021                  "o.__defineGetter__('foo', function() { throw new Error('get foo') }); "
2022                  "o.__defineSetter__('foo', function() { throw new Error('set foo') }); ");
2023     QJSValue object = eng.evaluate("o");
2024     QVERIFY(!eng.hasUncaughtException());
2025     QJSValue ret = object.property("foo");
2026     QVERIFY(ret.isError());
2027     QVERIFY(eng.hasUncaughtException());
2028     QVERIFY(ret.strictlyEquals(eng.uncaughtException()));
2029     QCOMPARE(ret.toString(), QLatin1String("Error: get foo"));
2030     eng.evaluate("Object"); // clear exception state...
2031     QVERIFY(!eng.hasUncaughtException());
2032     object.setProperty("foo", str);
2033     QVERIFY(eng.hasUncaughtException());
2034     QCOMPARE(eng.uncaughtException().toString(), QLatin1String("Error: set foo"));
2035 }
2036
2037 void tst_QJSValue::getSetProperty_gettersAndSettersOnNative()
2038 {
2039 #if 0 // FIXME: No c-style functions right now
2040     // attempt to install getter+setter on built-in (native) property
2041     QScriptEngine eng;
2042     QJSValue object = eng.newObject();
2043     QVERIFY(object.property("__proto__").strictlyEquals(object.prototype()));
2044
2045     QJSValue fun = eng.newFunction(getSet__proto__);
2046     fun.setProperty("value", QJSValue(&eng, "boo"));
2047 /*    QTest::ignoreMessage(QtWarningMsg, "QJSValue::setProperty() failed: "
2048                          "cannot set getter or setter of native property "
2049                          "`__proto__'");*/
2050     object.setProperty("__proto__", fun,
2051                         QJSValue::PropertyGetter | QJSValue::PropertySetter
2052                         | QJSValue::UserRange);
2053     QVERIFY(object.property("__proto__").strictlyEquals(object.prototype()));
2054
2055     object.setProperty("__proto__", QJSValue(),
2056                         QJSValue::PropertyGetter | QJSValue::PropertySetter);
2057     QVERIFY(object.property("__proto__").strictlyEquals(object.prototype()));
2058 #endif
2059 }
2060
2061 void tst_QJSValue::getSetProperty_gettersAndSettersOnGlobalObject()
2062 {
2063 #if 0 // FIXME: No c-style functions right now
2064     // global property that's a getter+setter
2065     QScriptEngine eng;
2066     eng.globalObject().setProperty("globalGetterSetterProperty", eng.newFunction(getterSetter),
2067                                    QJSValue::PropertyGetter | QJSValue::PropertySetter);
2068     eng.evaluate("globalGetterSetterProperty = 123");
2069     {
2070         QJSValue ret = eng.evaluate("globalGetterSetterProperty");
2071         QVERIFY(ret.isNumber());
2072         QVERIFY(ret.strictlyEquals(QJSValue(&eng, 123)));
2073     }
2074     QCOMPARE(eng.evaluate("typeof globalGetterSetterProperty").toString(),
2075              QString::fromLatin1("number"));
2076     {
2077         QJSValue ret = eng.evaluate("this.globalGetterSetterProperty()");
2078         QVERIFY(ret.isError());
2079         QCOMPARE(ret.toString(), QString::fromLatin1("TypeError: Property 'globalGetterSetterProperty' of object #<Object> is not a function"));
2080     }
2081     {
2082         QJSValue ret = eng.evaluate("new this.globalGetterSetterProperty()");
2083         QVERIFY(ret.isError());
2084         QCOMPARE(ret.toString(), QString::fromLatin1("TypeError: number is not a function"));
2085     }
2086 #endif
2087 }
2088
2089 void tst_QJSValue::getSetProperty_gettersAndSettersChange()
2090 {
2091 #if 0 // FIXME: No setters/getters API right now
2092     // "upgrading" an existing property to become a getter+setter
2093     QScriptEngine eng;
2094     QJSValue object = eng.newObject();
2095     QJSValue num(&eng, 123);
2096     object.setProperty("foo", num);
2097     object.setProperty("foo", eng.newFunction(getterSetter),
2098                         QJSValue::PropertyGetter | QJSValue::PropertySetter);
2099     QVERIFY(!object.property("x").isValid());
2100     object.setProperty("foo", num);
2101     QVERIFY(object.property("x").equals(num));
2102
2103     eng.globalObject().setProperty("object", object);
2104     QJSValue res = eng.evaluate("object.x = 89; var a = object.foo; object.foo = 65; a");
2105     QCOMPARE(res.toInt32(), 89);
2106     QCOMPARE(object.property("x").toInt32(), 65);
2107     QCOMPARE(object.property("foo").toInt32(), 65);
2108 #endif
2109 }
2110
2111 void tst_QJSValue::getSetProperty_array()
2112 {
2113     QJSEngine eng;
2114     QJSValue str = QJSValue(&eng, QLatin1String("bar"));
2115     QJSValue num = QJSValue(&eng, 123.0);
2116     QJSValue array = eng.newArray();
2117
2118     QVERIFY(array.isArray());
2119     array.setProperty(0, num);
2120     QCOMPARE(array.property(0).toNumber(), num.toNumber());
2121     QCOMPARE(array.property("0").toNumber(), num.toNumber());
2122     QCOMPARE(array.property("length").toUInt32(), quint32(1));
2123     array.setProperty(1, str);
2124     QCOMPARE(array.property(1).toString(), str.toString());
2125     QCOMPARE(array.property("1").toString(), str.toString());
2126     QCOMPARE(array.property("length").toUInt32(), quint32(2));
2127     array.setProperty("length", QJSValue(&eng, 1));
2128     QCOMPARE(array.property("length").toUInt32(), quint32(1));
2129     QCOMPARE(array.property(1).isValid(), false);
2130 }
2131
2132 void tst_QJSValue::getSetProperty_gettersAndSettersStupid()
2133 {
2134 #if 0 // FIXME: No setters/getters API right now
2135     //removing unexisting Setter or Getter should not crash.
2136     QScriptEngine eng;
2137     QJSValue num = QJSValue(&eng, 123.0);
2138
2139     {
2140         QJSValue object = eng.newObject();
2141         object.setProperty("foo", QJSValue(), QJSValue::PropertyGetter);
2142         QVERIFY(!object.property("foo").isValid());
2143         object.setProperty("foo", num);
2144         QCOMPARE(object.property("foo").strictlyEquals(num), true);
2145     }
2146
2147     {
2148         QJSValue object = eng.newObject();
2149         object.setProperty("foo", QJSValue(), QJSValue::PropertySetter);
2150         QVERIFY(!object.property("foo").isValid());
2151         object.setProperty("foo", num);
2152         QCOMPARE(object.property("foo").strictlyEquals(num), true);
2153     }
2154
2155     {
2156         QJSValue object = eng.globalObject();
2157         object.setProperty("foo", QJSValue(), QJSValue::PropertySetter);
2158         object.setProperty("foo", QJSValue(), QJSValue::PropertyGetter);
2159         QVERIFY(!object.property("foo").isValid());
2160         object.setProperty("foo", num);
2161         QCOMPARE(object.property("foo").strictlyEquals(num), true);
2162     }
2163 #endif
2164 }
2165
2166 void tst_QJSValue::getSetProperty()
2167 {
2168     QJSEngine eng;
2169
2170     QJSValue object = eng.newObject();
2171
2172     QJSValue str = QJSValue(&eng, QLatin1String("bar"));
2173     object.setProperty("foo", str);
2174     QCOMPARE(object.property("foo").toString(), str.toString());
2175
2176     QJSValue num = QJSValue(&eng, 123.0);
2177     object.setProperty("baz", num);
2178     QCOMPARE(object.property("baz").toNumber(), num.toNumber());
2179
2180     QJSValue strstr = QJSValue("bar");
2181     QCOMPARE(strstr.engine(), (QJSEngine *)0);
2182     object.setProperty("foo", strstr);
2183     QCOMPARE(object.property("foo").toString(), strstr.toString());
2184     QCOMPARE(strstr.engine(), &eng); // the value has been bound to the engine
2185
2186     QJSValue numnum = QJSValue(123.0);
2187     object.setProperty("baz", numnum);
2188     QCOMPARE(object.property("baz").toNumber(), numnum.toNumber());
2189
2190     QJSValue inv;
2191     inv.setProperty("foo", num);
2192     QCOMPARE(inv.property("foo").isValid(), false);
2193
2194     eng.globalObject().setProperty("object", object);
2195
2196 #if 0 // FIXME: no setProperty API with flags
2197   // ReadOnly
2198     object.setProperty("readOnlyProperty", num, QJSValue::ReadOnly);
2199     QCOMPARE(object.propertyFlags("readOnlyProperty"), QJSValue::ReadOnly);
2200     QCOMPARE(object.property("readOnlyProperty").strictlyEquals(num), true);
2201     eng.evaluate("object.readOnlyProperty = !object.readOnlyProperty");
2202     QCOMPARE(object.property("readOnlyProperty").strictlyEquals(num), true);
2203     // should still be part of enumeration
2204     {
2205         QJSValue ret = eng.evaluate(
2206             "found = false;"
2207             "for (var p in object) {"
2208             "  if (p == 'readOnlyProperty') {"
2209             "    found = true; break;"
2210             "  }"
2211             "} found");
2212         QCOMPARE(ret.strictlyEquals(QJSValue(&eng, true)), true);
2213     }
2214     // should still be deletable
2215     {
2216         QJSValue ret = eng.evaluate("delete object.readOnlyProperty");
2217         QCOMPARE(ret.strictlyEquals(QJSValue(&eng, true)), true);
2218         QCOMPARE(object.property("readOnlyProperty").isValid(), false);
2219     }
2220
2221   // Undeletable
2222     object.setProperty("undeletableProperty", num, QJSValue::Undeletable);
2223     QCOMPARE(object.propertyFlags("undeletableProperty"), QJSValue::Undeletable);
2224     QCOMPARE(object.property("undeletableProperty").strictlyEquals(num), true);
2225     {
2226         QJSValue ret = eng.evaluate("delete object.undeletableProperty");
2227         QCOMPARE(ret.strictlyEquals(QJSValue(&eng, true)), false);
2228         QCOMPARE(object.property("undeletableProperty").strictlyEquals(num), true);
2229     }
2230     // should still be writable
2231     eng.evaluate("object.undeletableProperty = object.undeletableProperty + 1");
2232     QCOMPARE(object.property("undeletableProperty").toNumber(), num.toNumber() + 1);
2233     // should still be part of enumeration
2234     {
2235         QJSValue ret = eng.evaluate(
2236             "found = false;"
2237             "for (var p in object) {"
2238             "  if (p == 'undeletableProperty') {"
2239             "    found = true; break;"
2240             "  }"
2241             "} found");
2242         QCOMPARE(ret.strictlyEquals(QJSValue(&eng, true)), true);
2243     }
2244     // should still be deletable from C++
2245     object.setProperty("undeletableProperty", QJSValue());
2246     QEXPECT_FAIL("", "QTBUG-17617: With JSC-based back-end, undeletable properties can't be deleted from C++", Continue);
2247     QVERIFY(!object.property("undeletableProperty").isValid());
2248     QEXPECT_FAIL("", "QTBUG-17617: With JSC-based back-end, undeletable properties can't be deleted from C++", Continue);
2249     QCOMPARE(object.propertyFlags("undeletableProperty"), 0);
2250
2251   // SkipInEnumeration
2252     object.setProperty("dontEnumProperty", num, QJSValue::SkipInEnumeration);
2253     QCOMPARE(object.propertyFlags("dontEnumProperty"), QJSValue::SkipInEnumeration);
2254     QCOMPARE(object.property("dontEnumProperty").strictlyEquals(num), true);
2255     // should not be part of enumeration
2256     {
2257         QJSValue ret = eng.evaluate(
2258             "found = false;"
2259             "for (var p in object) {"
2260             "  if (p == 'dontEnumProperty') {"
2261             "    found = true; break;"
2262             "  }"
2263             "} found");
2264         QCOMPARE(ret.strictlyEquals(QJSValue(&eng, false)), true);
2265     }
2266     // should still be writable
2267     eng.evaluate("object.dontEnumProperty = object.dontEnumProperty + 1");
2268     QCOMPARE(object.property("dontEnumProperty").toNumber(), num.toNumber() + 1);
2269     // should still be deletable
2270     {
2271         QJSValue ret = eng.evaluate("delete object.dontEnumProperty");
2272         QCOMPARE(ret.strictlyEquals(QJSValue(&eng, true)), true);
2273         QCOMPARE(object.property("dontEnumProperty").isValid(), false);
2274     }
2275
2276     // change flags
2277     object.setProperty("flagProperty", str);
2278     QCOMPARE(object.propertyFlags("flagProperty"), static_cast<QJSValue::PropertyFlags>(0));
2279
2280     QEXPECT_FAIL("", "FIXME: v8 does not support changing flags of existing properties", Continue);
2281     //v8::i::JSObject::SetProperty(LookupResult* result, ... ) does not take in account the attributes
2282     // if the result->isFound()
2283     object.setProperty("flagProperty", str, QJSValue::ReadOnly);
2284     QCOMPARE(object.propertyFlags("flagProperty"), QJSValue::ReadOnly);
2285
2286     QEXPECT_FAIL("", "FIXME: v8 does not support changing flags of existing properties", Continue);
2287     object.setProperty("flagProperty", str, object.propertyFlags("flagProperty") | QJSValue::SkipInEnumeration);
2288     QCOMPARE(object.propertyFlags("flagProperty"), QJSValue::ReadOnly | QJSValue::SkipInEnumeration);
2289
2290     QEXPECT_FAIL("", "FIXME: v8 does not support changing flags of existing properties", Continue);
2291     object.setProperty("flagProperty", str, QJSValue::KeepExistingFlags);
2292     QCOMPARE(object.propertyFlags("flagProperty"), QJSValue::ReadOnly | QJSValue::SkipInEnumeration);
2293
2294     QEXPECT_FAIL("", "FIXME: v8 does not support UserRange", Continue);
2295     object.setProperty("flagProperty", str, QJSValue::UserRange);
2296     QCOMPARE(object.propertyFlags("flagProperty"), QJSValue::UserRange);
2297
2298     // flags of property in the prototype
2299     {
2300         QJSValue object2 = eng.newObject();
2301         object2.setPrototype(object);
2302         QCOMPARE(object2.propertyFlags("flagProperty", QJSValue::ResolveLocal), 0);
2303         QEXPECT_FAIL("", "FIXME: v8 does not support UserRange", Continue);
2304         QCOMPARE(object2.propertyFlags("flagProperty"), QJSValue::UserRange);
2305     }
2306
2307     // using interned strings
2308     QScriptString foo = eng.toStringHandle("foo");
2309
2310     object.setProperty(foo, QJSValue());
2311     QVERIFY(!object.property(foo).isValid());
2312
2313     object.setProperty(foo, num);
2314     QVERIFY(object.property(foo).strictlyEquals(num));
2315     QVERIFY(object.property("foo").strictlyEquals(num));
2316     QVERIFY(object.propertyFlags(foo) == 0);
2317 #endif
2318
2319     // Setting index property on non-Array
2320     object.setProperty(13, num);
2321     QVERIFY(object.property(13).equals(num));
2322 }
2323
2324 void tst_QJSValue::arrayElementGetterSetter()
2325 {
2326 #if 0 // FIXME: No c-style functions
2327     QScriptEngine eng;
2328     QJSValue obj = eng.newObject();
2329     obj.setProperty(1, eng.newFunction(getterSetter), QJSValue::PropertyGetter|QJSValue::PropertySetter);
2330     {
2331         QJSValue num(123);
2332         obj.setProperty("x", num);
2333         QJSValue ret = obj.property(1);
2334         QVERIFY(ret.isValid());
2335         QVERIFY(ret.equals(num));
2336     }
2337     {
2338         QJSValue num(456);
2339         obj.setProperty(1, num);
2340         QJSValue ret = obj.property(1);
2341         QVERIFY(ret.isValid());
2342         QVERIFY(ret.equals(num));
2343         QVERIFY(ret.equals(obj.property("1")));
2344     }
2345     QCOMPARE(obj.propertyFlags("1"), QJSValue::PropertyGetter|QJSValue::PropertySetter);
2346
2347     obj.setProperty(1, QJSValue(), QJSValue::PropertyGetter|QJSValue::PropertySetter);
2348     QVERIFY(obj.propertyFlags("1") == 0);
2349 #endif
2350 }
2351
2352 void tst_QJSValue::getSetPrototype_cyclicPrototype()
2353 {
2354     QJSEngine eng;
2355     QJSValue prototype = eng.newObject();
2356     QJSValue object = eng.newObject();
2357     object.setPrototype(prototype);
2358
2359     QJSValue previousPrototype = prototype.prototype();
2360     QTest::ignoreMessage(QtWarningMsg, "QJSValue::setPrototype() failed: cyclic prototype value");
2361     prototype.setPrototype(prototype);
2362     QCOMPARE(prototype.prototype().strictlyEquals(previousPrototype), true);
2363
2364     object.setPrototype(prototype);
2365     QTest::ignoreMessage(QtWarningMsg, "QJSValue::setPrototype() failed: cyclic prototype value");
2366     prototype.setPrototype(object);
2367     QCOMPARE(prototype.prototype().strictlyEquals(previousPrototype), true);
2368
2369 }
2370
2371 void tst_QJSValue::getSetPrototype_evalCyclicPrototype()
2372 {
2373     QJSEngine eng;
2374     QJSValue ret = eng.evaluate("o = { }; p = { }; o.__proto__ = p; p.__proto__ = o");
2375     QCOMPARE(eng.hasUncaughtException(), true);
2376     QVERIFY(ret.strictlyEquals(eng.uncaughtException()));
2377     QCOMPARE(ret.isError(), true);
2378     QCOMPARE(ret.toString(), QLatin1String("Error: Cyclic __proto__ value"));
2379 }
2380
2381 void tst_QJSValue::getSetPrototype_eval()
2382 {
2383     QJSEngine eng;
2384     QJSValue ret = eng.evaluate("p = { }; p.__proto__ = { }");
2385     QCOMPARE(eng.hasUncaughtException(), false);
2386     QCOMPARE(ret.isError(), false);
2387 }
2388
2389 void tst_QJSValue::getSetPrototype_invalidPrototype()
2390 {
2391     QJSEngine eng;
2392     QJSValue inv;
2393     QJSValue object = eng.newObject();
2394     QJSValue proto = object.prototype();
2395     QVERIFY(object.prototype().strictlyEquals(proto));
2396     inv.setPrototype(object);
2397     QCOMPARE(inv.prototype().isValid(), false);
2398     object.setPrototype(inv);
2399     QVERIFY(object.prototype().strictlyEquals(proto));
2400 }
2401
2402 void tst_QJSValue::getSetPrototype_twoEngines()
2403 {
2404     QJSEngine eng;
2405     QJSValue prototype = eng.newObject();
2406     QJSValue object = eng.newObject();
2407     object.setPrototype(prototype);
2408     QJSEngine otherEngine;
2409     QJSValue newPrototype = otherEngine.newObject();
2410     QTest::ignoreMessage(QtWarningMsg, "QJSValue::setPrototype() failed: cannot set a prototype created in a different engine");
2411     object.setPrototype(newPrototype);
2412     QCOMPARE(object.prototype().strictlyEquals(prototype), true);
2413
2414 }
2415
2416 void tst_QJSValue::getSetPrototype_null()
2417 {
2418     QJSEngine eng;
2419     QJSValue object = eng.newObject();
2420     object.setPrototype(QJSValue(QJSValue::NullValue));
2421     QVERIFY(object.prototype().isNull());
2422
2423     QJSValue newProto = eng.newObject();
2424     object.setPrototype(newProto);
2425     QVERIFY(object.prototype().equals(newProto));
2426
2427     object.setPrototype(QJSValue(&eng, QJSValue::NullValue));
2428     QVERIFY(object.prototype().isNull());
2429 }
2430
2431 void tst_QJSValue::getSetPrototype_notObjectOrNull()
2432 {
2433     QJSEngine eng;
2434     QJSValue object = eng.newObject();
2435     QJSValue originalProto = object.prototype();
2436
2437     // bool
2438     object.setPrototype(true);
2439     QVERIFY(object.prototype().equals(originalProto));
2440     object.setPrototype(QJSValue(&eng, true));
2441     QVERIFY(object.prototype().equals(originalProto));
2442
2443     // number
2444     object.setPrototype(123);
2445     QVERIFY(object.prototype().equals(originalProto));
2446     object.setPrototype(QJSValue(&eng, 123));
2447     QVERIFY(object.prototype().equals(originalProto));
2448
2449     // string
2450     object.setPrototype("foo");
2451     QVERIFY(object.prototype().equals(originalProto));
2452     object.setPrototype(QJSValue(&eng, QLatin1String("foo")));
2453     QVERIFY(object.prototype().equals(originalProto));
2454
2455     // undefined
2456     object.setPrototype(QJSValue(QJSValue::UndefinedValue));
2457     QVERIFY(object.prototype().equals(originalProto));
2458     object.setPrototype(QJSValue(&eng, QJSValue::UndefinedValue));
2459     QVERIFY(object.prototype().equals(originalProto));
2460 }
2461
2462 void tst_QJSValue::getSetPrototype()
2463 {
2464     QJSEngine eng;
2465     QJSValue prototype = eng.newObject();
2466     QJSValue object = eng.newObject();
2467     object.setPrototype(prototype);
2468     QCOMPARE(object.prototype().strictlyEquals(prototype), true);
2469 }
2470
2471 void tst_QJSValue::getSetScope()
2472 {
2473 #if 0 // FIXME: No QJSValue::scope
2474     QScriptEngine eng;
2475
2476     QJSValue object = eng.newObject();
2477     QCOMPARE(object.scope().isValid(), false);
2478
2479     QJSValue object2 = eng.newObject();
2480     object2.setScope(object);
2481
2482     QEXPECT_FAIL("", "FIXME: scope not implemented yet", Abort);
2483     QCOMPARE(object2.scope().strictlyEquals(object), true);
2484
2485     object.setProperty("foo", 123);
2486     QVERIFY(!object2.property("foo").isValid());
2487     {
2488         QJSValue ret = object2.property("foo", QJSValue::ResolveScope);
2489         QVERIFY(ret.isNumber());
2490         QCOMPARE(ret.toInt32(), 123);
2491     }
2492
2493     QJSValue inv;
2494     inv.setScope(object);
2495     QCOMPARE(inv.scope().isValid(), false);
2496
2497     QScriptEngine otherEngine;
2498     QJSValue object3 = otherEngine.newObject();
2499     QTest::ignoreMessage(QtWarningMsg, "QJSValue::setScope() failed: cannot set a scope object created in a different engine");
2500     object2.setScope(object3);
2501     QCOMPARE(object2.scope().strictlyEquals(object), true);
2502
2503     object2.setScope(QJSValue());
2504     QVERIFY(!object2.scope().isValid());
2505 #endif
2506 }
2507
2508 void tst_QJSValue::getSetData_objects_data()
2509 {
2510 #if 0 // FIXME: no setData/data API
2511     newEngine();
2512
2513     QTest::addColumn<QJSValue>("object");
2514
2515     QTest::newRow("object from evaluate") << engine->evaluate("new Object()");
2516     QTest::newRow("object from engine") << engine->newObject();
2517     QTest::newRow("Array") << engine->newArray();
2518     QTest::newRow("Date") << engine->newDate(12324);
2519     QTest::newRow("QObject") << engine->newQObject(this);
2520     QTest::newRow("RegExp") << engine->newRegExp(QRegExp());
2521 #endif
2522 }
2523
2524 void tst_QJSValue::getSetData_objects()
2525 {
2526 #if 0 // FIXME: no setData/data API
2527     QFETCH(QJSValue, object);
2528
2529     QVERIFY(!object.data().isValid());
2530     QJSValue v1(true);
2531     object.setData(v1);
2532     QVERIFY(object.data().strictlyEquals(v1));
2533     QJSValue v2(123);
2534     object.setData(v2);
2535     QVERIFY(object.data().strictlyEquals(v2));
2536     QJSValue v3 = engine->newObject();
2537     object.setData(v3);
2538     QVERIFY(object.data().strictlyEquals(v3));
2539     object.setData(QJSValue());
2540     QVERIFY(!object.data().isValid());
2541 #endif
2542 }
2543
2544 void tst_QJSValue::getSetData_nonObjects_data()
2545 {
2546 #if 0 // FIXME: no setData/data API
2547     newEngine();
2548
2549     QTest::addColumn<QJSValue>("value");
2550
2551     QTest::newRow("undefined (bound)") << engine->undefinedValue();
2552     QTest::newRow("null (bound)") << engine->nullValue();
2553     QTest::newRow("string (bound)") << QJSValue(engine, "Pong");
2554     QTest::newRow("bool (bound)") << QJSValue(engine, false);
2555
2556     QTest::newRow("undefined") << QJSValue(QJSValue::UndefinedValue);
2557     QTest::newRow("null") << QJSValue(QJSValue::NullValue);
2558     QTest::newRow("string") << QJSValue("Pong");
2559     QTest::newRow("bool") << QJSValue(true);
2560 #endif
2561 }
2562
2563 void tst_QJSValue::getSetData_nonObjects()
2564 {
2565 #if 0 // FIXME: no setData/data API
2566     QFETCH(QJSValue, value);
2567
2568     QVERIFY(!value.data().isValid());
2569     QJSValue v1(true);
2570     value.setData(v1);
2571     QVERIFY(!value.data().isValid());
2572     QJSValue v2(123);
2573     value.setData(v2);
2574     QVERIFY(!value.data().isValid());
2575     QJSValue v3 = engine->newObject();
2576     value.setData(v3);
2577     QVERIFY(!value.data().isValid());
2578     value.setData(QJSValue());
2579     QVERIFY(!value.data().isValid());
2580 #endif
2581 }
2582
2583 void tst_QJSValue::setData_QTBUG15144()
2584 {
2585 #if 0 // FIXME: no setData/data API
2586     QScriptEngine eng;
2587     QJSValue obj = eng.newObject();
2588     for (int i = 0; i < 10000; ++i) {
2589         // Create an object with property 'fooN' on it, and immediately kill
2590         // the reference to the object so it and the property name become garbage.
2591         eng.evaluate(QString::fromLatin1("o = {}; o.foo%0 = 10; o = null;").arg(i));
2592         // Setting the data will cause a JS string to be allocated, which could
2593         // trigger a GC. This should not cause a crash.
2594         obj.setData("foodfight");
2595     }
2596 #endif
2597 }
2598
2599 #if 0 // FIXME: no QScriptClass
2600 class TestScriptClass : public QScriptClass
2601 {
2602 public:
2603     TestScriptClass(QScriptEngine *engine) : QScriptClass(engine) {}
2604 };
2605
2606 void tst_QJSValue::getSetScriptClass_emptyClass_data()
2607 {
2608     newEngine();
2609     QTest::addColumn<QJSValue>("value");
2610
2611     QTest::newRow("invalid") << QJSValue();
2612     QTest::newRow("number") << QJSValue(123);
2613     QTest::newRow("string") << QJSValue("pong");
2614     QTest::newRow("bool") << QJSValue(false);
2615     QTest::newRow("null") << QJSValue(QJSValue::NullValue);
2616     QTest::newRow("undefined") << QJSValue(QJSValue::UndefinedValue);
2617
2618     QTest::newRow("number") << QJSValue(engine, 123);
2619     QTest::newRow("string") << QJSValue(engine, "pong");
2620     QTest::newRow("bool") << QJSValue(engine, true);
2621     QTest::newRow("null") << QJSValue(engine->nullValue());
2622     QTest::newRow("undefined") << QJSValue(engine->undefinedValue());
2623     QTest::newRow("object") << QJSValue(engine->newObject());
2624     QTest::newRow("date") << QJSValue(engine->evaluate("new Date()"));
2625     QTest::newRow("qobject") << QJSValue(engine->newQObject(this));
2626 }
2627
2628 void tst_QJSValue::getSetScriptClass_emptyClass()
2629 {
2630     QFETCH(QJSValue, value);
2631     QCOMPARE(value.scriptClass(), (QScriptClass*)0);
2632 }
2633
2634 void tst_QJSValue::getSetScriptClass_JSObjectFromCpp()
2635 {
2636     QScriptEngine eng;
2637     TestScriptClass testClass(&eng);
2638     // object created in C++ (newObject())
2639     {
2640         QJSValue obj = eng.newObject();
2641         obj.setScriptClass(&testClass);
2642         QCOMPARE(obj.scriptClass(), (QScriptClass*)&testClass);
2643         obj.setScriptClass(0);
2644         QCOMPARE(obj.scriptClass(), (QScriptClass*)0);
2645     }
2646 }
2647
2648 void tst_QJSValue::getSetScriptClass_JSObjectFromJS()
2649 {
2650     QScriptEngine eng;
2651     TestScriptClass testClass(&eng);
2652     // object created in JS
2653     {
2654         QJSValue obj = eng.evaluate("new Object");
2655         QVERIFY(!eng.hasUncaughtException());
2656         QVERIFY(obj.isObject());
2657         QCOMPARE(obj.scriptClass(), (QScriptClass*)0);
2658         obj.setScriptClass(&testClass);
2659         QCOMPARE(obj.scriptClass(), (QScriptClass*)&testClass);
2660         obj.setScriptClass(0);
2661         QCOMPARE(obj.scriptClass(), (QScriptClass*)0);
2662     }
2663 }
2664
2665 void tst_QJSValue::getSetScriptClass_QVariant()
2666 {
2667     QScriptEngine eng;
2668     TestScriptClass testClass(&eng);
2669     // object that already has a(n internal) class
2670     {
2671         QJSValue obj = eng.newVariant(QUrl("http://example.com"));
2672         QVERIFY(obj.isVariant());
2673         QCOMPARE(obj.scriptClass(), (QScriptClass*)0);
2674         obj.setScriptClass(&testClass);
2675         QCOMPARE(obj.scriptClass(), (QScriptClass*)&testClass);
2676         QVERIFY(obj.isObject());
2677         QVERIFY(!obj.isVariant());
2678         QCOMPARE(obj.toVariant(), QVariant(QVariantMap()));
2679     }
2680 }
2681
2682 void tst_QJSValue::getSetScriptClass_QObject()
2683 {
2684     QScriptEngine eng;
2685     TestScriptClass testClass(&eng);
2686     {
2687         QJSValue obj = eng.newQObject(this);
2688         QVERIFY(obj.isQObject());
2689         obj.setScriptClass(&testClass);
2690         QCOMPARE(obj.scriptClass(), (QScriptClass*)&testClass);
2691         QVERIFY(obj.isObject());
2692         QVERIFY(!obj.isQObject());
2693         QVERIFY(obj.toQObject() == 0);
2694     }
2695 }
2696 #endif
2697
2698 #if 0 // FIXME: No c-style callbacks
2699 static QJSValue getArg(QScriptContext *ctx, QScriptEngine *)
2700 {
2701     return ctx->argument(0);
2702 }
2703
2704 static QJSValue evaluateArg(QScriptContext *, QScriptEngine *eng)
2705 {
2706     return eng->evaluate("arguments[0]");
2707 }
2708
2709 static QJSValue addArgs(QScriptContext *, QScriptEngine *eng)
2710 {
2711     return eng->evaluate("arguments[0] + arguments[1]");
2712 }
2713
2714 static QJSValue returnInvalidValue(QScriptContext *, QScriptEngine *)
2715 {
2716     return QJSValue();
2717 }
2718 #endif
2719
2720 void tst_QJSValue::call_function()
2721 {
2722     QJSEngine eng;
2723     QJSValue fun = eng.evaluate("(function() { return 1; })");
2724     QVERIFY(fun.isFunction());
2725     QJSValue result = fun.call();
2726     QVERIFY(result.isNumber());
2727     QCOMPARE(result.toInt32(), 1);
2728 }
2729
2730 void tst_QJSValue::call_object()
2731 {
2732     QJSEngine eng;
2733     QJSValue Object = eng.evaluate("Object");
2734     QCOMPARE(Object.isFunction(), true);
2735     QJSValue result = Object.call(Object);
2736     QCOMPARE(result.isObject(), true);
2737 }
2738
2739 void tst_QJSValue::call_newObjects()
2740 {
2741     QJSEngine eng;
2742     // test that call() doesn't construct new objects
2743     QJSValue Number = eng.evaluate("Number");
2744     QJSValue Object = eng.evaluate("Object");
2745     QCOMPARE(Object.isFunction(), true);
2746     QJSValueList args;
2747     args << QJSValue(&eng, 123);
2748     QJSValue result = Number.call(Object, args);
2749     QCOMPARE(result.strictlyEquals(args.at(0)), true);
2750 }
2751
2752 void tst_QJSValue::call_this()
2753 {
2754     QJSEngine eng;
2755     // test that correct "this" object is used
2756     QJSValue fun = eng.evaluate("(function() { return this; })");
2757     QCOMPARE(fun.isFunction(), true);
2758
2759     QJSValue numberObject = QJSValue(&eng, 123.0).toObject();
2760     QJSValue result = fun.call(numberObject);
2761     QCOMPARE(result.isObject(), true);
2762     QCOMPARE(result.toNumber(), 123.0);
2763 }
2764
2765 void tst_QJSValue::call_arguments()
2766 {
2767     QJSEngine eng;
2768     // test that correct arguments are passed
2769
2770     QJSValue fun = eng.evaluate("(function() { return arguments[0]; })");
2771     QCOMPARE(fun.isFunction(), true);
2772     {
2773         QJSValue result = fun.call(eng.undefinedValue());
2774         QCOMPARE(result.isUndefined(), true);
2775     }
2776     {
2777         QJSValueList args;
2778         args << QJSValue(&eng, 123.0);
2779         QJSValue result = fun.call(eng.undefinedValue(), args);
2780         QCOMPARE(result.isNumber(), true);
2781         QCOMPARE(result.toNumber(), 123.0);
2782     }
2783     // V2 constructors
2784     {
2785         QJSValueList args;
2786         args << QJSValue(123.0);
2787         QJSValue result = fun.call(eng.undefinedValue(), args);
2788         QCOMPARE(result.isNumber(), true);
2789         QCOMPARE(result.toNumber(), 123.0);
2790     }
2791 #if 0 // FIXME: The feature of interpreting a passed array as argument list has been removed from the API
2792     {
2793         QJSValue args = eng.newArray();
2794         args.setProperty(0, 123);
2795         QJSValue result = fun.call(eng.undefinedValue(), args);
2796         QVERIFY(result.isNumber());
2797         QCOMPARE(result.toNumber(), 123.0);
2798     }
2799 #endif
2800 }
2801
2802 void tst_QJSValue::call()
2803 {
2804     QJSEngine eng;
2805     {
2806         QJSValue fun = eng.evaluate("(function() { return arguments[1]; })");
2807         QCOMPARE(fun.isFunction(), true);
2808
2809         {
2810             QJSValueList args;
2811             args << QJSValue(&eng, 123.0) << QJSValue(&eng, 456.0);
2812             QJSValue result = fun.call(eng.undefinedValue(), args);
2813             QCOMPARE(result.isNumber(), true);
2814             QCOMPARE(result.toNumber(), 456.0);
2815         }
2816 #if 0 // FIXME: The feature of interpreting a passed array as argument list has been removed from the API
2817         {
2818             QJSValue args = eng.newArray();
2819             args.setProperty(0, 123);
2820             args.setProperty(1, 456);
2821             QJSValue result = fun.call(eng.undefinedValue(), args);
2822             QVERIFY(result.isNumber());
2823             QCOMPARE(result.toNumber(), 456.0);
2824         }
2825 #endif
2826     }
2827     {
2828         QJSValue fun = eng.evaluate("(function() { throw new Error('foo'); })");
2829         QCOMPARE(fun.isFunction(), true);
2830         QVERIFY(!eng.hasUncaughtException());
2831
2832         {
2833             QJSValue result = fun.call();
2834             QCOMPARE(result.isError(), true);
2835             QCOMPARE(eng.hasUncaughtException(), true);
2836             QVERIFY(result.strictlyEquals(eng.uncaughtException()));
2837         }
2838     }
2839 #if 0 // FIXME: No c-style callbacks
2840     {
2841         eng.clearExceptions();
2842         QJSValue fun = eng.newFunction(getArg);
2843         {
2844             QJSValueList args;
2845             args << QJSValue(&eng, 123.0);
2846             QJSValue result = fun.call(eng.undefinedValue(), args);
2847             QVERIFY(!eng.hasUncaughtException());
2848             QCOMPARE(result.isNumber(), true);
2849             QCOMPARE(result.toNumber(), 123.0);
2850         }
2851         // V2 constructors
2852         {
2853             QJSValueList args;
2854             args << QJSValue(123.0);
2855             QJSValue result = fun.call(eng.undefinedValue(), args);
2856             QCOMPARE(result.isNumber(), true);
2857             QCOMPARE(result.toNumber(), 123.0);
2858         }
2859 #if 0 // FIXME: The feature of interpreting a passed array as argument list has been removed from the API
2860         {
2861             QJSValue args = eng.newArray();
2862             args.setProperty(0, 123);
2863             QJSValue result = fun.call(eng.undefinedValue(), args);
2864             QVERIFY(result.isNumber());
2865             QCOMPARE(result.toNumber(), 123.0);
2866         }
2867 #endif
2868     }
2869     {
2870         QJSValue fun = eng.newFunction(evaluateArg);
2871         {
2872             QJSValueList args;
2873             args << QJSValue(&eng, 123.0);
2874             QJSValue result = fun.call(eng.undefinedValue(), args);
2875             QVERIFY(!eng.hasUncaughtException());
2876             QCOMPARE(result.isNumber(), true);
2877             QCOMPARE(result.toNumber(), 123.0);
2878         }
2879     }
2880 #endif
2881 }
2882
2883 void tst_QJSValue::call_invalidArguments()
2884 {
2885 #if 0 // FIXME: No c-style callbacks
2886     // test that invalid arguments are handled gracefully
2887     QScriptEngine eng;
2888     {
2889         QJSValue fun = eng.newFunction(getArg);
2890         {
2891             QJSValueList args;
2892             args << QJSValue();
2893             QJSValue ret = fun.call(QJSValue(), args);
2894             QVERIFY(!eng.hasUncaughtException());
2895             QCOMPARE(ret.isValid(), true);
2896             QCOMPARE(ret.isUndefined(), true);
2897         }
2898     }
2899     {
2900         QJSValue fun = eng.newFunction(evaluateArg);
2901         {
2902             QJSValueList args;
2903             args << QJSValue();
2904             QJSValue ret = fun.call(QJSValue(), args);
2905             QCOMPARE(ret.isValid(), true);
2906             QCOMPARE(ret.isUndefined(), true);
2907         }
2908     }
2909     {
2910         QJSValue fun = eng.newFunction(addArgs);
2911         {
2912             QJSValueList args;
2913             args << QJSValue() << QJSValue();
2914             QJSValue ret = fun.call(QJSValue(), args);
2915             QCOMPARE(ret.isValid(), true);
2916             QCOMPARE(ret.isNumber(), true);
2917             QCOMPARE(qIsNaN(ret.toNumber()), true);
2918         }
2919     }
2920 #endif
2921 }
2922
2923 void tst_QJSValue::call_invalidReturn()
2924 {
2925 #if 0 // FIXME: No c-style callbacks
2926     // test that invalid return value is handled gracefully
2927     QScriptEngine eng;
2928     QJSValue fun = eng.newFunction(returnInvalidValue);
2929     eng.globalObject().setProperty("returnInvalidValue", fun);
2930     QJSValue ret = eng.evaluate("returnInvalidValue() + returnInvalidValue()");
2931     QCOMPARE(ret.isValid(), true);
2932     QCOMPARE(ret.isNumber(), true);
2933     QCOMPARE(qIsNaN(ret.toNumber()), true);
2934 #endif
2935 }
2936
2937 void tst_QJSValue::call_twoEngines()
2938 {
2939     QJSEngine eng;
2940     QJSValue object = eng.evaluate("Object");
2941     QJSEngine otherEngine;
2942     QJSValue fun = otherEngine.evaluate("(function() { return 1; })");
2943     QVERIFY(fun.isFunction());
2944     QTest::ignoreMessage(QtWarningMsg, "JSValue can't be rassigned to an another engine.");
2945     QTest::ignoreMessage(QtWarningMsg, "QJSValue::call() failed: "
2946                          "cannot call function with thisObject created in "
2947                          "a different engine");
2948     QCOMPARE(fun.call(object).isValid(), false);
2949     QTest::ignoreMessage(QtWarningMsg, "QJSValue::call() failed: "
2950                          "cannot call function with argument created in "
2951                          "a different engine");
2952     QCOMPARE(fun.call(QJSValue(), QJSValueList() << QJSValue(&eng, 123)).isValid(), false);
2953     {
2954         QJSValue fun = eng.evaluate("Object");
2955         QVERIFY(fun.isFunction());
2956         QJSEngine eng2;
2957         QJSValue objectInDifferentEngine = eng2.newObject();
2958         QJSValueList args;
2959         args << objectInDifferentEngine;
2960         QTest::ignoreMessage(QtWarningMsg, "QJSValue::call() failed: cannot call function with argument created in a different engine");
2961         fun.call(QJSValue(), args);
2962     }
2963 }
2964
2965 void tst_QJSValue::call_array()
2966 {
2967 #if 0 // FIXME: The feature of interpreting an array as argument list has been removed from the API
2968     QScriptEngine eng;
2969     QJSValue fun = eng.evaluate("(function() { return arguments; })");
2970     QVERIFY(fun.isFunction());
2971     QJSValue array = eng.newArray(3);
2972     array.setProperty(0, QJSValue(&eng, 123.0));
2973     array.setProperty(1, QJSValue(&eng, 456.0));
2974     array.setProperty(2, QJSValue(&eng, 789.0));
2975     // call with single array object as arguments
2976     QJSValue ret = fun.call(QJSValue(), array);
2977     QVERIFY(!eng.hasUncaughtException());
2978     QCOMPARE(ret.isError(), false);
2979     QCOMPARE(ret.property(0).strictlyEquals(array.property(0)), true);
2980     QCOMPARE(ret.property(1).strictlyEquals(array.property(1)), true);
2981     QCOMPARE(ret.property(2).strictlyEquals(array.property(2)), true);
2982     // call with arguments object as arguments
2983     QJSValue ret2 = fun.call(QJSValue(), ret);
2984     QCOMPARE(ret2.isError(), false);
2985     QCOMPARE(ret2.property(0).strictlyEquals(ret.property(0)), true);
2986     QCOMPARE(ret2.property(1).strictlyEquals(ret.property(1)), true);
2987     QCOMPARE(ret2.property(2).strictlyEquals(ret.property(2)), true);
2988     // call with null as arguments
2989     QJSValue ret3 = fun.call(QJSValue(), eng.nullValue());
2990     QCOMPARE(ret3.isError(), false);
2991     QCOMPARE(ret3.property("length").isNumber(), true);
2992     QCOMPARE(ret3.property("length").toNumber(), 0.0);
2993     // call with undefined as arguments
2994     QJSValue ret4 = fun.call(QJSValue(), eng.undefinedValue());
2995     QCOMPARE(ret4.isError(), false);
2996     QCOMPARE(ret4.property("length").isNumber(), true);
2997     QCOMPARE(ret4.property("length").toNumber(), 0.0);
2998     // call with something else as arguments
2999     QJSValue ret5 = fun.call(QJSValue(), QJSValue(&eng, 123.0));
3000     QCOMPARE(ret5.isError(), true);
3001     // call with a non-array object as arguments
3002     QJSValue ret6 = fun.call(QJSValue(), eng.globalObject());
3003     QVERIFY(ret6.isError());
3004     QCOMPARE(ret6.toString(), QString::fromLatin1("TypeError: Arguments must be an array"));
3005 #endif
3006 }
3007
3008
3009 void tst_QJSValue::call_nonFunction_data()
3010 {
3011     newEngine();
3012     QTest::addColumn<QJSValue>("value");
3013
3014     QTest::newRow("invalid") << QJSValue();
3015     QTest::newRow("bool") << QJSValue(false);
3016     QTest::newRow("int") << QJSValue(123);
3017     QTest::newRow("string") << QJSValue(QString::fromLatin1("ciao"));
3018     QTest::newRow("undefined") << QJSValue(QJSValue::UndefinedValue);
3019     QTest::newRow("null") << QJSValue(QJSValue::NullValue);
3020
3021     QTest::newRow("bool bound") << QJSValue(engine, false);
3022     QTest::newRow("int bound") << QJSValue(engine, 123);
3023     QTest::newRow("string bound") << QJSValue(engine, QString::fromLatin1("ciao"));
3024     QTest::newRow("undefined bound") << engine->undefinedValue();
3025     QTest::newRow("null bound") << engine->nullValue();
3026 }
3027
3028 void tst_QJSValue::call_nonFunction()
3029 {
3030     // calling things that are not functions
3031     QFETCH(QJSValue, value);
3032     QVERIFY(!value.call().isValid());
3033 }
3034
3035 #if 0 // FIXME: no c-style callbacks
3036 static QJSValue ctorReturningUndefined(QScriptContext *ctx, QScriptEngine *)
3037 {
3038     ctx->thisObject().setProperty("foo", 123);
3039     return QJSValue(QJSValue::UndefinedValue);
3040 }
3041
3042 static QJSValue ctorReturningNewObject(QScriptContext *, QScriptEngine *eng)
3043 {
3044     QJSValue result = eng->newObject();
3045     result.setProperty("bar", 456);
3046     return result;
3047 }
3048 #endif
3049
3050 void tst_QJSValue::construct_nonFunction_data()
3051 {
3052     newEngine();
3053     QTest::addColumn<QJSValue>("value");
3054
3055     QTest::newRow("invalid") << QJSValue();
3056     QTest::newRow("bool") << QJSValue(false);
3057     QTest::newRow("int") << QJSValue(123);
3058     QTest::newRow("string") << QJSValue(QString::fromLatin1("ciao"));
3059     QTest::newRow("undefined") << QJSValue(QJSValue::UndefinedValue);
3060     QTest::newRow("null") << QJSValue(QJSValue::NullValue);
3061
3062     QTest::newRow("bool bound") << QJSValue(engine, false);
3063     QTest::newRow("int bound") << QJSValue(engine, 123);
3064     QTest::newRow("string bound") << QJSValue(engine, QString::fromLatin1("ciao"));
3065     QTest::newRow("undefined bound") << engine->undefinedValue();
3066     QTest::newRow("null bound") << engine->nullValue();
3067 }
3068
3069 void tst_QJSValue::construct_nonFunction()
3070 {
3071     QFETCH(QJSValue, value);
3072     QVERIFY(!value.construct().isValid());
3073 }
3074
3075 void tst_QJSValue::construct_simple()
3076 {
3077     QJSEngine eng;
3078     QJSValue fun = eng.evaluate("(function () { this.foo = 123; })");
3079     QVERIFY(fun.isFunction());
3080     QJSValue ret = fun.construct();
3081     QVERIFY(ret.isObject());
3082     QVERIFY(ret.instanceOf(fun));
3083     QCOMPARE(ret.property("foo").toInt32(), 123);
3084 }
3085
3086 void tst_QJSValue::construct_newObjectJS()
3087 {
3088     QJSEngine eng;
3089     // returning a different object overrides the default-constructed one
3090     QJSValue fun = eng.evaluate("(function () { return { bar: 456 }; })");
3091     QVERIFY(fun.isFunction());
3092     QJSValue ret = fun.construct();
3093     QVERIFY(ret.isObject());
3094     QVERIFY(!ret.instanceOf(fun));
3095     QCOMPARE(ret.property("bar").toInt32(), 456);
3096 }
3097
3098 #if 0 // FIXME: no c-style callbacks
3099 void tst_QJSValue::construct_undefined()
3100 {
3101     QScriptEngine eng;
3102     QJSValue fun = eng.newFunction(ctorReturningUndefined);
3103     QJSValue ret = fun.construct();
3104     QVERIFY(ret.isObject());
3105     QVERIFY(ret.instanceOf(fun));
3106     QCOMPARE(ret.property("foo").toInt32(), 123);
3107 }
3108
3109 void tst_QJSValue::construct_newObjectCpp()
3110 {
3111     QScriptEngine eng;
3112     QJSValue fun = eng.newFunction(ctorReturningNewObject);
3113     QJSValue ret = fun.construct();
3114     QVERIFY(ret.isObject());
3115     QVERIFY(!ret.instanceOf(fun));
3116     QCOMPARE(ret.property("bar").toInt32(), 456);
3117 }
3118 #endif
3119
3120 void tst_QJSValue::construct_arg()
3121 {
3122     QJSEngine eng;
3123     QJSValue Number = eng.evaluate("Number");
3124     QCOMPARE(Number.isFunction(), true);
3125     QJSValueList args;
3126     args << QJSValue(&eng, 123);
3127     QJSValue ret = Number.construct(args);
3128     QCOMPARE(ret.isObject(), true);
3129     QCOMPARE(ret.toNumber(), args.at(0).toNumber());
3130 }
3131
3132 void tst_QJSValue::construct_proto()
3133 {
3134     QJSEngine eng;
3135     // test that internal prototype is set correctly
3136     QJSValue fun = eng.evaluate("(function() { return this.__proto__; })");
3137     QCOMPARE(fun.isFunction(), true);
3138     QCOMPARE(fun.property("prototype").isObject(), true);
3139     QJSValue ret = fun.construct();
3140     QCOMPARE(fun.property("prototype").strictlyEquals(ret), true);
3141 }
3142
3143 void tst_QJSValue::construct_returnInt()
3144 {
3145     QJSEngine eng;
3146     // test that we return the new object even if a non-object value is returned from the function
3147     QJSValue fun = eng.evaluate("(function() { return 123; })");
3148     QCOMPARE(fun.isFunction(), true);
3149     QJSValue ret = fun.construct();
3150     QCOMPARE(ret.isObject(), true);
3151 }
3152
3153 void tst_QJSValue::construct_throw()
3154 {
3155     QJSEngine eng;
3156     QJSValue fun = eng.evaluate("(function() { throw new Error('foo'); })");
3157     QCOMPARE(fun.isFunction(), true);
3158     QJSValue ret = fun.construct();
3159     QCOMPARE(ret.isError(), true);
3160     QCOMPARE(eng.hasUncaughtException(), true);
3161     QVERIFY(ret.strictlyEquals(eng.uncaughtException()));
3162 }
3163
3164 #if 0 // FIXME: The feature of interpreting an array as argument list has been removed from the API
3165 void tst_QJSValue::construct()
3166 {
3167     QScriptEngine eng;
3168     QJSValue fun = eng.evaluate("(function() { return arguments; })");
3169     QVERIFY(fun.isFunction());
3170     QJSValue array = eng.newArray(3);
3171     array.setProperty(0, QJSValue(&eng, 123.0));
3172     array.setProperty(1, QJSValue(&eng, 456.0));
3173     array.setProperty(2, QJSValue(&eng, 789.0));
3174     // construct with single array object as arguments
3175     QJSValue ret = fun.construct(array);
3176     QVERIFY(!eng.hasUncaughtException());
3177     QVERIFY(ret.isValid());
3178     QVERIFY(ret.isObject());
3179     QCOMPARE(ret.property(0).strictlyEquals(array.property(0)), true);
3180     QCOMPARE(ret.property(1).strictlyEquals(array.property(1)), true);
3181     QCOMPARE(ret.property(2).strictlyEquals(array.property(2)), true);
3182     // construct with arguments object as arguments
3183     QJSValue ret2 = fun.construct(ret);
3184     QCOMPARE(ret2.property(0).strictlyEquals(ret.property(0)), true);
3185     QCOMPARE(ret2.property(1).strictlyEquals(ret.property(1)), true);
3186     QCOMPARE(ret2.property(2).strictlyEquals(ret.property(2)), true);
3187     // construct with null as arguments
3188     QJSValue ret3 = fun.construct(eng.nullValue());
3189     QCOMPARE(ret3.isError(), false);
3190     QCOMPARE(ret3.property("length").isNumber(), true);
3191     QCOMPARE(ret3.property("length").toNumber(), 0.0);
3192     // construct with undefined as arguments
3193     QJSValue ret4 = fun.construct(eng.undefinedValue());
3194     QCOMPARE(ret4.isError(), false);
3195     QCOMPARE(ret4.property("length").isNumber(), true);
3196     QCOMPARE(ret4.property("length").toNumber(), 0.0);
3197     // construct with something else as arguments
3198     QJSValue ret5 = fun.construct(QJSValue(&eng, 123.0));
3199     QCOMPARE(ret5.isError(), true);
3200     // construct with a non-array object as arguments
3201     QJSValue ret6 = fun.construct(eng.globalObject());
3202     QVERIFY(ret6.isError());
3203     QCOMPARE(ret6.toString(), QString::fromLatin1("TypeError: Arguments must be an array"));
3204 }
3205 #endif
3206
3207 void tst_QJSValue::construct_twoEngines()
3208 {
3209     QJSEngine engine;
3210     QJSEngine otherEngine;
3211     QJSValue ctor = engine.evaluate("(function (a, b) { this.foo = 123; })");
3212     QJSValue arg(&otherEngine, 124567);
3213     QTest::ignoreMessage(QtWarningMsg, "QJSValue::construct() failed: cannot construct function with argument created in a different engine");
3214     QVERIFY(!ctor.construct(QJSValueList() << arg).isValid());
3215     QTest::ignoreMessage(QtWarningMsg, "QJSValue::construct() failed: cannot construct function with argument created in a different engine");
3216     QVERIFY(!ctor.construct(QJSValueList() << arg << otherEngine.newObject()).isValid());
3217 }
3218
3219 void tst_QJSValue::construct_constructorThrowsPrimitive()
3220 {
3221     QJSEngine eng;
3222     QJSValue fun = eng.evaluate("(function() { throw 123; })");
3223     QVERIFY(fun.isFunction());
3224     // construct(QJSValueList)
3225     {
3226         QJSValue ret = fun.construct();
3227         QVERIFY(ret.isNumber());
3228         QCOMPARE(ret.toNumber(), 123.0);
3229         QVERIFY(eng.hasUncaughtException());
3230         QVERIFY(ret.strictlyEquals(eng.uncaughtException()));
3231         eng.clearExceptions();
3232     }
3233 #if 0 // FIXME: The feature of interpreting an array as argument list has been removed from the API
3234     // construct(QJSValue)
3235     {
3236         QJSValue ret = fun.construct(eng.newArray());
3237         QVERIFY(ret.isNumber());
3238         QCOMPARE(ret.toNumber(), 123.0);
3239         QVERIFY(eng.hasUncaughtException());
3240         QVERIFY(ret.strictlyEquals(eng.uncaughtException()));
3241         eng.clearExceptions();
3242     }
3243 #endif
3244 }
3245
3246 #if 0 // FIXME: No QJSValue::lessThan
3247 void tst_QJSValue::lessThan()
3248 {
3249     QScriptEngine eng;
3250
3251     QVERIFY(!QJSValue().lessThan(QJSValue()));
3252
3253     QJSValue num = QJSValue(&eng, 123);
3254     QCOMPARE(num.lessThan(QJSValue(&eng, 124)), true);
3255     QCOMPARE(num.lessThan(QJSValue(&eng, 122)), false);
3256     QCOMPARE(num.lessThan(QJSValue(&eng, 123)), false);
3257     QCOMPARE(num.lessThan(QJSValue(&eng, "124")), true);
3258     QCOMPARE(num.lessThan(QJSValue(&eng, "122")), false);
3259     QCOMPARE(num.lessThan(QJSValue(&eng, "123")), false);
3260     QCOMPARE(num.lessThan(QJSValue(&eng, qSNaN())), false);
3261     QCOMPARE(num.lessThan(QJSValue(&eng, +qInf())), true);
3262     QCOMPARE(num.lessThan(QJSValue(&eng, -qInf())), false);
3263     QCOMPARE(num.lessThan(num), false);
3264     QCOMPARE(num.lessThan(QJSValue(&eng, 124).toObject()), true);
3265     QCOMPARE(num.lessThan(QJSValue(&eng, 122).toObject()), false);
3266     QCOMPARE(num.lessThan(QJSValue(&eng, 123).toObject()), false);
3267     QCOMPARE(num.lessThan(QJSValue(&eng, "124").toObject()), true);
3268     QCOMPARE(num.lessThan(QJSValue(&eng, "122").toObject()), false);
3269     QCOMPARE(num.lessThan(QJSValue(&eng, "123").toObject()), false);
3270     QCOMPARE(num.lessThan(QJSValue(&eng, qSNaN()).toObject()), false);
3271     QCOMPARE(num.lessThan(QJSValue(&eng, +qInf()).toObject()), true);
3272     QCOMPARE(num.lessThan(QJSValue(&eng, -qInf()).toObject()), false);
3273     QCOMPARE(num.lessThan(num.toObject()), false);
3274     QCOMPARE(num.lessThan(QJSValue()), false);
3275
3276     QJSValue str = QJSValue(&eng, "123");
3277     QCOMPARE(str.lessThan(QJSValue(&eng, "124")), true);
3278     QCOMPARE(str.lessThan(QJSValue(&eng, "122")), false);
3279     QCOMPARE(str.lessThan(QJSValue(&eng, "123")), false);
3280     QCOMPARE(str.lessThan(QJSValue(&eng, 124)), true);
3281     QCOMPARE(str.lessThan(QJSValue(&eng, 122)), false);
3282     QCOMPARE(str.lessThan(QJSValue(&eng, 123)), false);
3283     QCOMPARE(str.lessThan(str), false);
3284     QCOMPARE(str.lessThan(QJSValue(&eng, "124").toObject()), true);
3285     QCOMPARE(str.lessThan(QJSValue(&eng, "122").toObject()), false);
3286     QCOMPARE(str.lessThan(QJSValue(&eng, "123").toObject()), false);
3287     QCOMPARE(str.lessThan(QJSValue(&eng, 124).toObject()), true);
3288     QCOMPARE(str.lessThan(QJSValue(&eng, 122).toObject()), false);
3289     QCOMPARE(str.lessThan(QJSValue(&eng, 123).toObject()), false);
3290     QCOMPARE(str.lessThan(str.toObject()), false);
3291     QCOMPARE(str.lessThan(QJSValue()), false);
3292
3293     // V2 constructors
3294     QJSValue num2 = QJSValue(123);
3295     QCOMPARE(num2.lessThan(QJSValue(124)), true);
3296     QCOMPARE(num2.lessThan(QJSValue(122)), false);
3297     QCOMPARE(num2.lessThan(QJSValue(123)), false);
3298     QCOMPARE(num2.lessThan(QJSValue("124")), true);
3299     QCOMPARE(num2.lessThan(QJSValue("122")), false);
3300     QCOMPARE(num2.lessThan(QJSValue("123")), false);
3301     QCOMPARE(num2.lessThan(QJSValue(qSNaN())), false);
3302     QCOMPARE(num2.lessThan(QJSValue(+qInf())), true);
3303     QCOMPARE(num2.lessThan(QJSValue(-qInf())), false);
3304     QCOMPARE(num2.lessThan(num), false);
3305     QCOMPARE(num2.lessThan(QJSValue()), false);
3306
3307     QJSValue str2 = QJSValue("123");
3308     QCOMPARE(str2.lessThan(QJSValue("124")), true);
3309     QCOMPARE(str2.lessThan(QJSValue("122")), false);
3310     QCOMPARE(str2.lessThan(QJSValue("123")), false);
3311     QCOMPARE(str2.lessThan(QJSValue(124)), true);
3312     QCOMPARE(str2.lessThan(QJSValue(122)), false);
3313     QCOMPARE(str2.lessThan(QJSValue(123)), false);
3314     QCOMPARE(str2.lessThan(str), false);
3315     QCOMPARE(str2.lessThan(QJSValue()), false);
3316
3317     QJSValue obj1 = eng.newObject();
3318     QJSValue obj2 = eng.newObject();
3319     QCOMPARE(obj1.lessThan(obj2), false);
3320     QCOMPARE(obj2.lessThan(obj1), false);
3321     QCOMPARE(obj1.lessThan(obj1), false);
3322     QCOMPARE(obj2.lessThan(obj2), false);
3323
3324     QJSValue date1 = eng.newDate(QDateTime(QDate(2000, 1, 1)));
3325     QJSValue date2 = eng.newDate(QDateTime(QDate(1999, 1, 1)));
3326     QCOMPARE(date1.lessThan(date2), false);
3327     QCOMPARE(date2.lessThan(date1), true);
3328     QCOMPARE(date1.lessThan(date1), false);
3329     QCOMPARE(date2.lessThan(date2), false);
3330     QCOMPARE(date1.lessThan(QJSValue()), false);
3331
3332     QCOMPARE(QJSValue().lessThan(date2), false);
3333
3334     QScriptEngine otherEngine;
3335     QTest::ignoreMessage(QtWarningMsg, "QJSValue::lessThan: "
3336                          "cannot compare to a value created in "
3337                          "a different engine");
3338     QCOMPARE(date1.lessThan(QJSValue(&otherEngine, 123)), false);
3339 }
3340 #endif
3341
3342 void tst_QJSValue::equals()
3343 {
3344     QJSEngine eng;
3345
3346     QVERIFY(QJSValue().equals(QJSValue()));
3347
3348     QJSValue num = QJSValue(&eng, 123);
3349     QCOMPARE(num.equals(QJSValue(&eng, 123)), true);
3350     QCOMPARE(num.equals(QJSValue(&eng, 321)), false);
3351     QCOMPARE(num.equals(QJSValue(&eng, QLatin1String("123"))), true);
3352     QCOMPARE(num.equals(QJSValue(&eng, QLatin1String("321"))), false);
3353     QCOMPARE(num.equals(QJSValue(&eng, 123).toObject()), true);
3354     QCOMPARE(num.equals(QJSValue(&eng, 321).toObject()), false);
3355     QCOMPARE(num.equals(QJSValue(&eng, QLatin1String("123")).toObject()), true);
3356     QCOMPARE(num.equals(QJSValue(&eng, QLatin1String("321")).toObject()), false);
3357     QVERIFY(num.toObject().equals(num));
3358     QCOMPARE(num.equals(QJSValue()), false);
3359
3360     QJSValue str = QJSValue(&eng, QLatin1String("123"));
3361     QCOMPARE(str.equals(QJSValue(&eng, QLatin1String("123"))), true);
3362     QCOMPARE(str.equals(QJSValue(&eng, QLatin1String("321"))), false);
3363     QCOMPARE(str.equals(QJSValue(&eng, 123)), true);
3364     QCOMPARE(str.equals(QJSValue(&eng, 321)), false);
3365     QCOMPARE(str.equals(QJSValue(&eng, QLatin1String("123")).toObject()), true);
3366     QCOMPARE(str.equals(QJSValue(&eng, QLatin1String("321")).toObject()), false);
3367     QCOMPARE(str.equals(QJSValue(&eng, 123).toObject()), true);
3368     QCOMPARE(str.equals(QJSValue(&eng, 321).toObject()), false);
3369     QVERIFY(str.toObject().equals(str));
3370     QCOMPARE(str.equals(QJSValue()), false);
3371
3372     QJSValue num2 = QJSValue(123);
3373     QCOMPARE(num2.equals(QJSValue(123)), true);
3374     QCOMPARE(num2.equals(QJSValue(321)), false);
3375     QCOMPARE(num2.equals(QJSValue("123")), true);
3376     QCOMPARE(num2.equals(QJSValue("321")), false);
3377     QCOMPARE(num2.equals(QJSValue()), false);
3378
3379     QJSValue str2 = QJSValue("123");
3380     QCOMPARE(str2.equals(QJSValue("123")), true);
3381     QCOMPARE(str2.equals(QJSValue("321")), false);
3382     QCOMPARE(str2.equals(QJSValue(123)), true);
3383     QCOMPARE(str2.equals(QJSValue(321)), false);
3384     QCOMPARE(str2.equals(QJSValue()), false);
3385
3386     QJSValue date1 = eng.newDate(QDateTime(QDate(2000, 1, 1)));
3387     QJSValue date2 = eng.newDate(QDateTime(QDate(1999, 1, 1)));
3388     QCOMPARE(date1.equals(date2), false);
3389     QCOMPARE(date1.equals(date1), true);
3390     QCOMPARE(date2.equals(date2), true);
3391
3392     QJSValue undefined = eng.undefinedValue();
3393     QJSValue null = eng.nullValue();
3394     QCOMPARE(undefined.equals(undefined), true);
3395     QCOMPARE(null.equals(null), true);
3396     QCOMPARE(undefined.equals(null), true);
3397     QCOMPARE(null.equals(undefined), true);
3398     QCOMPARE(undefined.equals(QJSValue()), false);
3399     QCOMPARE(null.equals(QJSValue()), false);
3400     QVERIFY(!null.equals(num));
3401     QVERIFY(!undefined.equals(num));
3402
3403     QJSValue sant = QJSValue(&eng, true);
3404     QVERIFY(sant.equals(QJSValue(&eng, 1)));
3405     QVERIFY(sant.equals(QJSValue(&eng, QLatin1String("1"))));
3406     QVERIFY(sant.equals(sant));
3407     QVERIFY(sant.equals(QJSValue(&eng, 1).toObject()));
3408     QVERIFY(sant.equals(QJSValue(&eng, QLatin1String("1")).toObject()));
3409     QVERIFY(sant.equals(sant.toObject()));
3410     QVERIFY(sant.toObject().equals(sant));
3411     QVERIFY(!sant.equals(QJSValue(&eng, 0)));
3412     QVERIFY(!sant.equals(undefined));
3413     QVERIFY(!sant.equals(null));
3414
3415     QJSValue falskt = QJSValue(&eng, false);
3416     QVERIFY(falskt.equals(QJSValue(&eng, 0)));
3417     QVERIFY(falskt.equals(QJSValue(&eng, QLatin1String("0"))));
3418     QVERIFY(falskt.equals(falskt));
3419     QVERIFY(falskt.equals(QJSValue(&eng, 0).toObject()));
3420     QVERIFY(falskt.equals(QJSValue(&eng, QLatin1String("0")).toObject()));
3421     QVERIFY(falskt.equals(falskt.toObject()));
3422     QVERIFY(falskt.toObject().equals(falskt));
3423     QVERIFY(!falskt.equals(sant));
3424     QVERIFY(!falskt.equals(undefined));
3425     QVERIFY(!falskt.equals(null));
3426
3427     QJSValue obj1 = eng.newObject();
3428     QJSValue obj2 = eng.newObject();
3429     QCOMPARE(obj1.equals(obj2), false);
3430     QCOMPARE(obj2.equals(obj1), false);
3431     QCOMPARE(obj1.equals(obj1), true);
3432     QCOMPARE(obj2.equals(obj2), true);
3433
3434     QJSValue qobj1 = eng.newQObject(this);
3435     QJSValue qobj2 = eng.newQObject(this);
3436     QJSValue qobj3 = eng.newQObject(0);
3437
3438     // FIXME: No ScriptOwnership: QJSValue qobj4 = eng.newQObject(new QObject(), QScriptEngine::ScriptOwnership);
3439     QJSValue qobj4 = eng.newQObject(new QObject());
3440
3441     QVERIFY(qobj1.equals(qobj2)); // compares the QObject pointers
3442     QVERIFY(!qobj2.equals(qobj4)); // compares the QObject pointers
3443     QVERIFY(!qobj2.equals(obj2)); // compares the QObject pointers
3444
3445     QJSValue compareFun = eng.evaluate("(function(a, b) { return a == b; })");
3446     QVERIFY(compareFun.isFunction());
3447     {
3448         QJSValue ret = compareFun.call(QJSValue(), QJSValueList() << qobj1 << qobj2);
3449         QVERIFY(ret.isBool());
3450         ret = compareFun.call(QJSValue(), QJSValueList() << qobj1 << qobj3);
3451         QVERIFY(ret.isBool());
3452         QVERIFY(!ret.toBool());
3453         ret = compareFun.call(QJSValue(), QJSValueList() << qobj1 << qobj4);
3454         QVERIFY(ret.isBool());
3455         QVERIFY(!ret.toBool());
3456         ret = compareFun.call(QJSValue(), QJSValueList() << qobj1 << obj1);
3457         QVERIFY(ret.isBool());
3458         QVERIFY(!ret.toBool());
3459     }
3460
3461     {
3462         QJSValue var1 = eng.newVariant(QVariant(false));
3463         QJSValue var2 = eng.newVariant(QVariant(false));
3464         QEXPECT_FAIL("", "FIXME: QVariant comparison does not work with v8", Continue);
3465         QVERIFY(var1.equals(var2));
3466         {
3467             QJSValue ret = compareFun.call(QJSValue(), QJSValueList() << var1 << var2);
3468             QVERIFY(ret.isBool());
3469         }
3470     }
3471     {
3472         QJSValue var1 = eng.newVariant(QVariant(false));
3473         QJSValue var2 = eng.newVariant(QVariant(0));
3474         // QVariant::operator==() performs type conversion
3475         QEXPECT_FAIL("", "FIXME: QVariant comparison does not work with v8", Continue);
3476         QVERIFY(var1.equals(var2));
3477     }
3478     {
3479         QJSValue var1 = eng.newVariant(QVariant(QStringList() << "a"));
3480         QJSValue var2 = eng.newVariant(QVariant(QStringList() << "a"));
3481         QEXPECT_FAIL("", "FIXME: QVariant comparison does not work with v8", Continue);
3482         QVERIFY(var1.equals(var2));
3483     }
3484     {
3485         QJSValue var1 = eng.newVariant(QVariant(QStringList() << "a"));
3486         QJSValue var2 = eng.newVariant(QVariant(QStringList() << "b"));
3487         QVERIFY(!var1.equals(var2));
3488     }
3489     {
3490         QJSValue var1 = eng.newVariant(QVariant(QPoint(1, 2)));
3491         QJSValue var2 = eng.newVariant(QVariant(QPoint(1, 2)));
3492         QEXPECT_FAIL("", "FIXME: QVariant comparison does not work with v8", Continue);
3493         QVERIFY(var1.equals(var2));
3494     }
3495     {
3496         QJSValue var1 = eng.newVariant(QVariant(QPoint(1, 2)));
3497         QJSValue var2 = eng.newVariant(QVariant(QPoint(3, 4)));
3498         QVERIFY(!var1.equals(var2));
3499     }
3500     {
3501         QJSValue var1 = eng.newVariant(QVariant(int(1)));
3502         QJSValue var2 = eng.newVariant(QVariant(double(1)));
3503         // QVariant::operator==() performs type conversion
3504         QEXPECT_FAIL("", "FIXME: QVariant comparison does not work with v8", Continue);
3505         QVERIFY(var1.equals(var2));
3506     }
3507     {
3508         QJSValue var1 = eng.newVariant(QVariant(QString::fromLatin1("123")));
3509         QJSValue var2 = eng.newVariant(QVariant(double(123)));
3510         QJSValue var3(QString::fromLatin1("123"));
3511         QJSValue var4(123);
3512
3513         QVERIFY(var1.equals(var1));
3514         QEXPECT_FAIL("", "FIXME: QVariant comparison does not work with v8", Continue);
3515         QVERIFY(var1.equals(var2));
3516         QVERIFY(var1.equals(var3));
3517         QVERIFY(var1.equals(var4));
3518
3519         QEXPECT_FAIL("", "FIXME: QVariant comparison does not work with v8", Continue);
3520         QVERIFY(var2.equals(var1));
3521         QVERIFY(var2.equals(var2));
3522         QVERIFY(var2.equals(var3));
3523         QVERIFY(var2.equals(var4));
3524
3525         QVERIFY(var3.equals(var1));
3526         QVERIFY(var3.equals(var2));
3527         QVERIFY(var3.equals(var3));
3528         QVERIFY(var3.equals(var4));
3529
3530         QVERIFY(var4.equals(var1));
3531         QVERIFY(var4.equals(var2));
3532         QVERIFY(var4.equals(var3));
3533         QVERIFY(var4.equals(var4));
3534     }
3535
3536     QJSEngine otherEngine;
3537     QTest::ignoreMessage(QtWarningMsg, "QJSValue::equals: "
3538                          "cannot compare to a value created in "
3539                          "a different engine");
3540     QCOMPARE(date1.equals(QJSValue(&otherEngine, 123)), false);
3541 }
3542
3543 void tst_QJSValue::strictlyEquals()
3544 {
3545     QJSEngine eng;
3546
3547     QVERIFY(QJSValue().strictlyEquals(QJSValue()));
3548
3549     QJSValue num = QJSValue(&eng, 123);
3550     QCOMPARE(num.strictlyEquals(QJSValue(&eng, 123)), true);
3551     QCOMPARE(num.strictlyEquals(QJSValue(&eng, 321)), false);
3552     QCOMPARE(num.strictlyEquals(QJSValue(&eng, QLatin1String("123"))), false);
3553     QCOMPARE(num.strictlyEquals(QJSValue(&eng, QLatin1String("321"))), false);
3554     QCOMPARE(num.strictlyEquals(QJSValue(&eng, 123).toObject()), false);
3555     QCOMPARE(num.strictlyEquals(QJSValue(&eng, 321).toObject()), false);
3556     QCOMPARE(num.strictlyEquals(QJSValue(&eng, QLatin1String("123")).toObject()), false);
3557     QCOMPARE(num.strictlyEquals(QJSValue(&eng, QLatin1String("321")).toObject()), false);
3558     QVERIFY(!num.toObject().strictlyEquals(num));
3559     QVERIFY(!num.strictlyEquals(QJSValue()));
3560     QVERIFY(!QJSValue().strictlyEquals(num));
3561
3562     QJSValue str = QJSValue(&eng, QLatin1String("123"));
3563     QCOMPARE(str.strictlyEquals(QJSValue(&eng, QLatin1String("123"))), true);
3564     QCOMPARE(str.strictlyEquals(QJSValue(&eng, QLatin1String("321"))), false);
3565     QCOMPARE(str.strictlyEquals(QJSValue(&eng, 123)), false);
3566     QCOMPARE(str.strictlyEquals(QJSValue(&eng, 321)), false);
3567     QCOMPARE(str.strictlyEquals(QJSValue(&eng, QLatin1String("123")).toObject()), false);
3568     QCOMPARE(str.strictlyEquals(QJSValue(&eng, QLatin1String("321")).toObject()), false);
3569     QCOMPARE(str.strictlyEquals(QJSValue(&eng, 123).toObject()), false);
3570     QCOMPARE(str.strictlyEquals(QJSValue(&eng, 321).toObject()), false);
3571     QVERIFY(!str.toObject().strictlyEquals(str));
3572     QVERIFY(!str.strictlyEquals(QJSValue()));
3573
3574     QJSValue num2 = QJSValue(123);
3575     QCOMPARE(num2.strictlyEquals(QJSValue(123)), true);
3576     QCOMPARE(num2.strictlyEquals(QJSValue(321)), false);
3577     QCOMPARE(num2.strictlyEquals(QJSValue("123")), false);
3578     QCOMPARE(num2.strictlyEquals(QJSValue("321")), false);
3579     QVERIFY(!num2.strictlyEquals(QJSValue()));
3580
3581     QJSValue str2 = QJSValue("123");
3582     QCOMPARE(str2.strictlyEquals(QJSValue("123")), true);
3583     QCOMPARE(str2.strictlyEquals(QJSValue("321")), false);
3584     QCOMPARE(str2.strictlyEquals(QJSValue(123)), false);
3585     QCOMPARE(str2.strictlyEquals(QJSValue(321)), false);
3586     QVERIFY(!str2.strictlyEquals(QJSValue()));
3587
3588     QJSValue date1 = eng.newDate(QDateTime(QDate(2000, 1, 1)));
3589     QJSValue date2 = eng.newDate(QDateTime(QDate(1999, 1, 1)));
3590     QCOMPARE(date1.strictlyEquals(date2), false);
3591     QCOMPARE(date1.strictlyEquals(date1), true);
3592     QCOMPARE(date2.strictlyEquals(date2), true);
3593     QVERIFY(!date1.strictlyEquals(QJSValue()));
3594
3595     QJSValue undefined = eng.undefinedValue();
3596     QJSValue null = eng.nullValue();
3597     QCOMPARE(undefined.strictlyEquals(undefined), true);
3598     QCOMPARE(null.strictlyEquals(null), true);
3599     QCOMPARE(undefined.strictlyEquals(null), false);
3600     QCOMPARE(null.strictlyEquals(undefined), false);
3601     QVERIFY(!null.strictlyEquals(QJSValue()));
3602
3603     QJSValue sant = QJSValue(&eng, true);
3604     QVERIFY(!sant.strictlyEquals(QJSValue(&eng, 1)));
3605     QVERIFY(!sant.strictlyEquals(QJSValue(&eng, QLatin1String("1"))));
3606     QVERIFY(sant.strictlyEquals(sant));
3607     QVERIFY(!sant.strictlyEquals(QJSValue(&eng, 1).toObject()));
3608     QVERIFY(!sant.strictlyEquals(QJSValue(&eng, QLatin1String("1")).toObject()));
3609     QVERIFY(!sant.strictlyEquals(sant.toObject()));
3610     QVERIFY(!sant.toObject().strictlyEquals(sant));
3611     QVERIFY(!sant.strictlyEquals(QJSValue(&eng, 0)));
3612     QVERIFY(!sant.strictlyEquals(undefined));
3613     QVERIFY(!sant.strictlyEquals(null));
3614     QVERIFY(!sant.strictlyEquals(QJSValue()));
3615
3616     QJSValue falskt = QJSValue(&eng, false);
3617     QVERIFY(!falskt.strictlyEquals(QJSValue(&eng, 0)));
3618     QVERIFY(!falskt.strictlyEquals(QJSValue(&eng, QLatin1String("0"))));
3619     QVERIFY(falskt.strictlyEquals(falskt));
3620     QVERIFY(!falskt.strictlyEquals(QJSValue(&eng, 0).toObject()));
3621     QVERIFY(!falskt.strictlyEquals(QJSValue(&eng, QLatin1String("0")).toObject()));
3622     QVERIFY(!falskt.strictlyEquals(falskt.toObject()));
3623     QVERIFY(!falskt.toObject().strictlyEquals(falskt));
3624     QVERIFY(!falskt.strictlyEquals(sant));
3625     QVERIFY(!falskt.strictlyEquals(undefined));
3626     QVERIFY(!falskt.strictlyEquals(null));
3627     QVERIFY(!falskt.strictlyEquals(QJSValue()));
3628
3629     QVERIFY(!QJSValue(false).strictlyEquals(123));
3630     QVERIFY(!QJSValue(QJSValue::UndefinedValue).strictlyEquals(123));
3631     QVERIFY(!QJSValue(QJSValue::NullValue).strictlyEquals(123));
3632     QVERIFY(!QJSValue(false).strictlyEquals("ciao"));
3633     QVERIFY(!QJSValue(QJSValue::UndefinedValue).strictlyEquals("ciao"));
3634     QVERIFY(!QJSValue(QJSValue::NullValue).strictlyEquals("ciao"));
3635     QVERIFY(QJSValue(&eng, QLatin1String("ciao")).strictlyEquals("ciao"));
3636     QVERIFY(QJSValue("ciao").strictlyEquals(QJSValue(&eng, QLatin1String("ciao"))));
3637     QVERIFY(!QJSValue("ciao").strictlyEquals(123));
3638     QVERIFY(!QJSValue("ciao").strictlyEquals(QJSValue(&eng, 123)));
3639     QVERIFY(!QJSValue(123).strictlyEquals("ciao"));
3640     QVERIFY(!QJSValue(123).strictlyEquals(QJSValue(&eng, QLatin1String("ciao"))));
3641     QVERIFY(!QJSValue(&eng, 123).strictlyEquals("ciao"));
3642
3643     QJSValue obj1 = eng.newObject();
3644     QJSValue obj2 = eng.newObject();
3645     QCOMPARE(obj1.strictlyEquals(obj2), false);
3646     QCOMPARE(obj2.strictlyEquals(obj1), false);
3647     QCOMPARE(obj1.strictlyEquals(obj1), true);
3648     QCOMPARE(obj2.strictlyEquals(obj2), true);
3649     QVERIFY(!obj1.strictlyEquals(QJSValue()));
3650
3651     QJSValue qobj1 = eng.newQObject(this);
3652     QJSValue qobj2 = eng.newQObject(this);
3653     QVERIFY(qobj1.strictlyEquals(qobj2));
3654
3655     {
3656         QJSValue var1 = eng.newVariant(QVariant(false));
3657         QJSValue var2 = eng.newVariant(QVariant(false));
3658         QVERIFY(!var1.strictlyEquals(var2));
3659         QVERIFY(!var1.strictlyEquals(QJSValue()));
3660     }
3661     {
3662         QJSValue var1 = eng.newVariant(QVariant(false));
3663         QJSValue var2 = eng.newVariant(QVariant(0));
3664         QVERIFY(!var1.strictlyEquals(var2));
3665     }
3666     {
3667         QJSValue var1 = eng.newVariant(QVariant(QStringList() << "a"));
3668         QJSValue var2 = eng.newVariant(QVariant(QStringList() << "a"));
3669         QVERIFY(!var1.strictlyEquals(var2));
3670     }
3671     {
3672         QJSValue var1 = eng.newVariant(QVariant(QStringList() << "a"));
3673         QJSValue var2 = eng.newVariant(QVariant(QStringList() << "b"));
3674         QVERIFY(!var1.strictlyEquals(var2));
3675     }
3676     {
3677         QJSValue var1 = eng.newVariant(QVariant(QPoint(1, 2)));
3678         QJSValue var2 = eng.newVariant(QVariant(QPoint(1, 2)));
3679         QVERIFY(!var1.strictlyEquals(var2));
3680     }
3681     {
3682         QJSValue var1 = eng.newVariant(QVariant(QPoint(1, 2)));
3683         QJSValue var2 = eng.newVariant(QVariant(QPoint(3, 4)));
3684         QVERIFY(!var1.strictlyEquals(var2));
3685     }
3686
3687     QJSEngine otherEngine;
3688     QTest::ignoreMessage(QtWarningMsg, "QJSValue::strictlyEquals: "
3689                          "cannot compare to a value created in "
3690                          "a different engine");
3691     QCOMPARE(date1.strictlyEquals(QJSValue(&otherEngine, 123)), false);
3692 }
3693
3694 Q_DECLARE_METATYPE(int*)
3695 Q_DECLARE_METATYPE(double*)
3696 Q_DECLARE_METATYPE(QColor*)
3697 Q_DECLARE_METATYPE(QBrush*)
3698
3699 void tst_QJSValue::castToPointer()
3700 {
3701     QJSEngine eng;
3702     {
3703         QJSValue v = eng.newVariant(int(123));
3704         int *ip = qjsvalue_cast<int*>(v);
3705         QVERIFY(ip != 0);
3706         QCOMPARE(*ip, 123);
3707         *ip = 456;
3708         QCOMPARE(qjsvalue_cast<int>(v), 456);
3709
3710         double *dp = qjsvalue_cast<double*>(v);
3711         QVERIFY(dp == 0);
3712
3713         QJSValue v2 = eng.newVariant(qVariantFromValue(ip));
3714         QCOMPARE(qjsvalue_cast<int*>(v2), ip);
3715     }
3716     {
3717         QColor c(123, 210, 231);
3718         QJSValue v = eng.newVariant(c);
3719         QColor *cp = qjsvalue_cast<QColor*>(v);
3720         QVERIFY(cp != 0);
3721         QCOMPARE(*cp, c);
3722
3723         QBrush *bp = qjsvalue_cast<QBrush*>(v);
3724         QVERIFY(bp == 0);
3725
3726         QJSValue v2 = eng.newVariant(qVariantFromValue(cp));
3727         QCOMPARE(qjsvalue_cast<QColor*>(v2), cp);
3728     }
3729 }
3730
3731 void tst_QJSValue::prettyPrinter_data()
3732 {
3733     QTest::addColumn<QString>("function");
3734     QTest::addColumn<QString>("expected");
3735     QTest::newRow("function() { }") << QString("function() { }") << QString("function () { }");
3736     QTest::newRow("function foo() { }") << QString("(function foo() { })") << QString("function foo() { }");
3737     QTest::newRow("function foo(bar) { }") << QString("(function foo(bar) { })") << QString("function foo(bar) { }");
3738     QTest::newRow("function foo(bar, baz) { }") << QString("(function foo(bar, baz) { })") << QString("function foo(bar, baz) { }");
3739     QTest::newRow("this") << QString("function() { this; }") << QString("function () { this; }");
3740     QTest::newRow("identifier") << QString("function(a) { a; }") << QString("function (a) { a; }");
3741     QTest::newRow("null") << QString("function() { null; }") << QString("function () { null; }");
3742     QTest::newRow("true") << QString("function() { true; }") << QString("function () { true; }");
3743     QTest::newRow("false") << QString("function() { false; }") << QString("function () { false; }");
3744     QTest::newRow("string") << QString("function() { 'test'; }") << QString("function () { \'test\'; }");
3745     QTest::newRow("string") << QString("function() { \"test\"; }") << QString("function () { \"test\"; }");
3746     QTest::newRow("number") << QString("function() { 123; }") << QString("function () { 123; }");
3747     QTest::newRow("number") << QString("function() { 123.456; }") << QString("function () { 123.456; }");
3748     QTest::newRow("regexp") << QString("function() { /hello/; }") << QString("function () { /hello/; }");
3749     QTest::newRow("regexp") << QString("function() { /hello/gim; }") << QString("function () { /hello/gim; }");
3750     QTest::newRow("array") << QString("function() { []; }") << QString("function () { []; }");
3751     QTest::newRow("array") << QString("function() { [10]; }") << QString("function () { [10]; }");
3752     QTest::newRow("array") << QString("function() { [10, 20, 30]; }") << QString("function () { [10, 20, 30]; }");
3753     QTest::newRow("array") << QString("function() { [10, 20, , 40]; }") << QString("function () { [10, 20, , 40]; }");
3754     QTest::newRow("array") << QString("function() { [,]; }") << QString("function () { [,]; }");
3755     QTest::newRow("array") << QString("function() { [, 10]; }") << QString("function () { [, 10]; }");
3756     QTest::newRow("array") << QString("function() { [, 10, ]; }") << QString("function () { [, 10, ]; }");
3757     QTest::newRow("array") << QString("function() { [, 10, ,]; }") << QString("function () { [, 10, ,]; }");
3758     QTest::newRow("array") << QString("function() { [[10], [20]]; }") << QString("function () { [[10], [20]]; }");
3759     QTest::newRow("member") << QString("function() { a.b; }") << QString("function () { a.b; }");
3760     QTest::newRow("member") << QString("function() { a.b.c; }") << QString("function () { a.b.c; }");
3761     QTest::newRow("call") << QString("function() { f(); }") << QString("function () { f(); }");
3762     QTest::newRow("call") << QString("function() { f(a); }") << QString("function () { f(a); }");
3763     QTest::newRow("call") << QString("function() { f(a, b); }") << QString("function () { f(a, b); }");
3764     QTest::newRow("new") << QString("function() { new C(); }") << QString("function () { new C(); }");
3765     QTest::newRow("new") << QString("function() { new C(a); }") << QString("function () { new C(a); }");
3766     QTest::newRow("new") << QString("function() { new C(a, b); }") << QString("function () { new C(a, b); }");
3767     QTest::newRow("++") << QString("function() { a++; }") << QString("function () { a++; }");
3768     QTest::newRow("++") << QString("function() { ++a; }") << QString("function () { ++a; }");
3769     QTest::newRow("--") << QString("function() { a--; }") << QString("function () { a--; }");
3770     QTest::newRow("--") << QString("function() { --a; }") << QString("function () { --a; }");
3771     QTest::newRow("delete") << QString("function() { delete a; }") << QString("function () { delete a; }");
3772     QTest::newRow("void") << QString("function() { void a; }") << QString("function () { void a; }");
3773     QTest::newRow("typeof") << QString("function() { typeof a; }") << QString("function () { typeof a; }");
3774     QTest::newRow("+") << QString("function() { +a; }") << QString("function () { +a; }");
3775     QTest::newRow("-") << QString("function() { -a; }") << QString("function () { -a; }");
3776     QTest::newRow("~") << QString("function() { ~a; }") << QString("function () { ~a; }");
3777     QTest::newRow("!") << QString("function() { !a; }") << QString("function () { !a; }");
3778     QTest::newRow("+") << QString("function() { a + b; }") << QString("function () { a + b; }");
3779     QTest::newRow("&&") << QString("function() { a && b; }") << QString("function () { a && b; }");
3780     QTest::newRow("&=") << QString("function() { a &= b; }") << QString("function () { a &= b; }");
3781     QTest::newRow("=") << QString("function() { a = b; }") << QString("function () { a = b; }");
3782     QTest::newRow("&") << QString("function() { a & b; }") << QString("function () { a & b; }");
3783     QTest::newRow("|") << QString("function() { a | b; }") << QString("function () { a | b; }");
3784     QTest::newRow("^") << QString("function() { a ^ b; }") << QString("function () { a ^ b; }");
3785     QTest::newRow("-=") << QString("function() { a -= b; }") << QString("function () { a -= b; }");
3786     QTest::newRow("/") << QString("function() { a / b; }") << QString("function () { a / b; }");
3787     QTest::newRow("/=") << QString("function() { a /= b; }") << QString("function () { a /= b; }");
3788     QTest::newRow("==") << QString("function() { a == b; }") << QString("function () { a == b; }");
3789     QTest::newRow(">=") << QString("function() { a >= b; }") << QString("function () { a >= b; }");
3790     QTest::newRow(">") << QString("function() { a > b; }") << QString("function () { a > b; }");
3791     QTest::newRow("in") << QString("function() { a in b; }") << QString("function () { a in b; }");
3792     QTest::newRow("+=") << QString("function() { a += b; }") << QString("function () { a += b; }");
3793     QTest::newRow("instanceof") << QString("function() { a instanceof b; }") << QString("function () { a instanceof b; }");
3794     QTest::newRow("<=") << QString("function() { a <= b; }") << QString("function () { a <= b; }");
3795     QTest::newRow("<<") << QString("function() { a << b; }") << QString("function () { a << b; }");
3796     QTest::newRow("<<=") << QString("function() { a <<= b; }") << QString("function () { a <<= b; }");
3797     QTest::newRow("<") << QString("function() { a < b; }") << QString("function () { a < b; }");
3798     QTest::newRow("%") << QString("function() { a % b; }") << QString("function () { a % b; }");
3799     QTest::newRow("%=") << QString("function() { a %= b; }") << QString("function () { a %= b; }");
3800     QTest::newRow("*") << QString("function() { a * b; }") << QString("function () { a * b; }");
3801     QTest::newRow("*=") << QString("function() { a *= b; }") << QString("function () { a *= b; }");
3802     QTest::newRow("!=") << QString("function() { a != b; }") << QString("function () { a != b; }");
3803     QTest::newRow("||") << QString("function() { a || b; }") << QString("function () { a || b; }");
3804     QTest::newRow("|=") << QString("function() { a |= b; }") << QString("function () { a |= b; }");
3805     QTest::newRow(">>") << QString("function() { a >> b; }") << QString("function () { a >> b; }");
3806     QTest::newRow(">>=") << QString("function() { a >>= b; }") << QString("function () { a >>= b; }");
3807     QTest::newRow("===") << QString("function() { a === b; }") << QString("function () { a === b; }");
3808     QTest::newRow("!==") << QString("function() { a !== b; }") << QString("function () { a !== b; }");
3809     QTest::newRow("-") << QString("function() { a - b; }") << QString("function () { a - b; }");
3810     QTest::newRow(">>>") << QString("function() { a >>> b; }") << QString("function () { a >>> b; }");
3811     QTest::newRow(">>>=") << QString("function() { a >>>= b; }") << QString("function () { a >>>= b; }");
3812     QTest::newRow("^=") << QString("function() { a ^= b; }") << QString("function () { a ^= b; }");
3813     QTest::newRow("? :") << QString("function() { a ? b : c; }") << QString("function () { a ? b : c; }");
3814     QTest::newRow("a; b; c") << QString("function() { a; b; c; }") << QString("function () { a; b; c; }");
3815     QTest::newRow("var a;") << QString("function() { var a; }") << QString("function () { var a; }");
3816     QTest::newRow("var a, b;") << QString("function() { var a, b; }") << QString("function () { var a, b; }");
3817     QTest::newRow("var a = 10;") << QString("function() { var a = 10; }") << QString("function () { var a = 10; }");
3818     QTest::newRow("var a, b = 20;") << QString("function() { var a, b = 20; }") << QString("function () { var a, b = 20; }");
3819     QTest::newRow("var a = 10, b = 20;") << QString("function() { var a = 10, b = 20; }") << QString("function () { var a = 10, b = 20; }");
3820     QTest::newRow("if") << QString("function() { if (a) b; }") << QString("function () { if (a) b; }");
3821     QTest::newRow("if") << QString("function() { if (a) { b; c; } }") << QString("function () { if (a) { b; c; } }");
3822     QTest::newRow("if-else") << QString("function() { if (a) b; else c; }") << QString("function () { if (a) b; else c; }");
3823     QTest::newRow("if-else") << QString("function() { if (a) { b; c; } else { d; e; } }") << QString("function () { if (a) { b; c; } else { d; e; } }");
3824     QTest::newRow("do-while") << QString("function() { do { a; } while (b); }") << QString("function () { do { a; } while (b); }");
3825     QTest::newRow("do-while") << QString("function() { do { a; b; c; } while (d); }") << QString("function () { do { a; b; c; } while (d); }");
3826     QTest::newRow("while") << QString("function() { while (a) { b; } }") << QString("function () { while (a) { b; } }");
3827     QTest::newRow("while") << QString("function() { while (a) { b; c; } }") << QString("function () { while (a) { b; c; } }");
3828     QTest::newRow("for") << QString("function() { for (a; b; c) { } }") << QString("function () { for (a; b; c) { } }");
3829     QTest::newRow("for") << QString("function() { for (; a; b) { } }") << QString("function () { for (; a; b) { } }");
3830     QTest::newRow("for") << QString("function() { for (; ; a) { } }") << QString("function () { for (; ; a) { } }");
3831     QTest::newRow("for") << QString("function() { for (; ; ) { } }") << QString("function () { for (; ; ) { } }");
3832     QTest::newRow("for") << QString("function() { for (var a; b; c) { } }") << QString("function () { for (var a; b; c) { } }");
3833     QTest::newRow("for") << QString("function() { for (var a, b, c; d; e) { } }") << QString("function () { for (var a, b, c; d; e) { } }");
3834     QTest::newRow("continue") << QString("function() { for (; ; ) { continue; } }") << QString("function () { for (; ; ) { continue; } }");
3835     QTest::newRow("break") << QString("function() { for (; ; ) { break; } }") << QString("function () { for (; ; ) { break; } }");
3836     QTest::newRow("return") << QString("function() { return; }") << QString("function () { return; }");
3837     QTest::newRow("return") << QString("function() { return 10; }") << QString("function () { return 10; }");
3838     QTest::newRow("with") << QString("function() { with (a) { b; } }") << QString("function () { with (a) { b; } }");
3839     QTest::newRow("with") << QString("function() { with (a) { b; c; } }") << QString("function () { with (a) { b; c; } }");
3840     QTest::newRow("switch") << QString("function() { switch (a) { } }") << QString("function () { switch (a) { } }");
3841     QTest::newRow("switch") << QString("function() { switch (a) { case 1: ; } }") << QString("function () { switch (a) { case 1: ; } }");
3842     QTest::newRow("switch") << QString("function() { switch (a) { case 1: b; break; } }") << QString("function () { switch (a) { case 1: b; break; } }");
3843     QTest::newRow("switch") << QString("function() { switch (a) { case 1: b; break; case 2: break; } }") << QString("function () { switch (a) { case 1: b; break; case 2: break; } }");
3844     QTest::newRow("switch") << QString("function() { switch (a) { case 1: case 2: ; } }") << QString("function () { switch (a) { case 1: case 2: ; } }");
3845     QTest::newRow("switch") << QString("function() { switch (a) { case 1: default: ; } }") << QString("function () { switch (a) { case 1: default: ; } }");
3846     QTest::newRow("switch") << QString("function() { switch (a) { case 1: default: ; case 3: ; } }") << QString("function () { switch (a) { case 1: default: ; case 3: ; } }");
3847     QTest::newRow("label") << QString("function() { a: b; }") << QString("function () { a: b; }");
3848     QTest::newRow("throw") << QString("function() { throw a; }") << QString("function () { throw a; }");
3849     QTest::newRow("try-catch") << QString("function() { try { a; } catch (e) { b; } }") << QString("function () { try { a; } catch (e) { b; } }");
3850     QTest::newRow("try-finally") << QString("function() { try { a; } finally { b; } }") << QString("function () { try { a; } finally { b; } }");
3851     QTest::newRow("try-catch-finally") << QString("function() { try { a; } catch (e) { b; } finally { c; } }") << QString("function () { try { a; } catch (e) { b; } finally { c; } }");
3852     QTest::newRow("a + b + c + d") << QString("function() { a + b + c + d; }") << QString("function () { a + b + c + d; }");
3853     QTest::newRow("a + b - c") << QString("function() { a + b - c; }") << QString("function () { a + b - c; }");
3854     QTest::newRow("a + -b") << QString("function() { a + -b; }") << QString("function () { a + -b; }");
3855     QTest::newRow("a + ~b") << QString("function() { a + ~b; }") << QString("function () { a + ~b; }");
3856     QTest::newRow("a + !b") << QString("function() { a + !b; }") << QString("function () { a + !b; }");
3857     QTest::newRow("a + +b") << QString("function() { a + +b; }") << QString("function () { a + +b; }");
3858     QTest::newRow("(a + b) - c") << QString("function() { (a + b) - c; }") << QString("function () { (a + b) - c; }");
3859     QTest::newRow("(a - b + c") << QString("function() { a - b + c; }") << QString("function () { a - b + c; }");
3860     QTest::newRow("(a - (b + c)") << QString("function() { a - (b + c); }") << QString("function () { a - (b + c); }");
3861     QTest::newRow("a + -(b + c)") << QString("function() { a + -(b + c); }") << QString("function () { a + -(b + c); }");
3862     QTest::newRow("a + ~(b + c)") << QString("function() { a + ~(b + c); }") << QString("function () { a + ~(b + c); }");
3863     QTest::newRow("a + !(b + c)") << QString("function() { a + !(b + c); }") << QString("function () { a + !(b + c); }");
3864     QTest::newRow("a + +(b + c)") << QString("function() { a + +(b + c); }") << QString("function () { a + +(b + c); }");
3865     QTest::newRow("a + b * c") << QString("function() { a + b * c; }") << QString("function () { a + b * c; }");
3866     QTest::newRow("(a + b) * c") << QString("function() { (a + b) * c; }") << QString("function () { (a + b) * c; }");
3867     QTest::newRow("(a + b) * (c + d)") << QString("function() { (a + b) * (c + d); }") << QString("function () { (a + b) * (c + d); }");
3868     QTest::newRow("a + (b * c)") << QString("function() { a + (b * c); }") << QString("function () { a + (b * c); }");
3869     QTest::newRow("a + (b / c)") << QString("function() { a + (b / c); }") << QString("function () { a + (b / c); }");
3870     QTest::newRow("(a / b) * c") << QString("function() { (a / b) * c; }") << QString("function () { (a / b) * c; }");
3871     QTest::newRow("a / (b * c)") << QString("function() { a / (b * c); }") << QString("function () { a / (b * c); }");
3872     QTest::newRow("a / (b % c)") << QString("function() { a / (b % c); }") << QString("function () { a / (b % c); }");
3873     QTest::newRow("a && b || c") << QString("function() { a && b || c; }") << QString("function () { a && b || c; }");
3874     QTest::newRow("a && (b || c)") << QString("function() { a && (b || c); }") << QString("function () { a && (b || c); }");
3875     QTest::newRow("a & b | c") << QString("function() { a & b | c; }") << QString("function () { a & b | c; }");
3876     QTest::newRow("a & (b | c)") << QString("function() { a & (b | c); }") << QString("function () { a & (b | c); }");
3877     QTest::newRow("a & b | c ^ d") << QString("function() { a & b | c ^ d; }") << QString("function () { a & b | c ^ d; }");
3878     QTest::newRow("a & (b | c ^ d)") << QString("function() { a & (b | c ^ d); }") << QString("function () { a & (b | c ^ d); }");
3879     QTest::newRow("(a & b | c) ^ d") << QString("function() { (a & b | c) ^ d; }") << QString("function () { (a & b | c) ^ d; }");
3880     QTest::newRow("a << b + c") << QString("function() { a << b + c; }") << QString("function () { a << b + c; }");
3881     QTest::newRow("(a << b) + c") << QString("function() { (a << b) + c; }") << QString("function () { (a << b) + c; }");
3882     QTest::newRow("a >> b + c") << QString("function() { a >> b + c; }") << QString("function () { a >> b + c; }");
3883     QTest::newRow("(a >> b) + c") << QString("function() { (a >> b) + c; }") << QString("function () { (a >> b) + c; }");
3884     QTest::newRow("a >>> b + c") << QString("function() { a >>> b + c; }") << QString("function () { a >>> b + c; }");
3885     QTest::newRow("(a >>> b) + c") << QString("function() { (a >>> b) + c; }") << QString("function () { (a >>> b) + c; }");
3886     QTest::newRow("a == b || c != d") << QString("function() { a == b || c != d; }") << QString("function () { a == b || c != d; }");
3887     QTest::newRow("a == (b || c != d)") << QString("function() { a == (b || c != d); }") << QString("function () { a == (b || c != d); }");
3888     QTest::newRow("a === b || c !== d") << QString("function() { a === b || c !== d; }") << QString("function () { a === b || c !== d; }");
3889     QTest::newRow("a === (b || c !== d)") << QString("function() { a === (b || c !== d); }") << QString("function () { a === (b || c !== d); }");
3890     QTest::newRow("a &= b + c") << QString("function() { a &= b + c; }") << QString("function () { a &= b + c; }");
3891     QTest::newRow("debugger") << QString("function() { debugger; }") << QString("function () { debugger; }");
3892 }
3893
3894 void tst_QJSValue::prettyPrinter()
3895 {
3896     QFETCH(QString, function);
3897     QFETCH(QString, expected);
3898     QJSEngine eng;
3899     QJSValue val = eng.evaluate("(" + function + ")");
3900     QVERIFY(val.isFunction());
3901     QString actual = val.toString();
3902     int count = qMin(actual.size(), expected.size());
3903 //    qDebug() << actual << expected;
3904     for (int i = 0; i < count; ++i) {
3905 //        qDebug() << i << actual.at(i) << expected.at(i);
3906         QCOMPARE(actual.at(i), expected.at(i));
3907     }
3908     QCOMPARE(actual.size(), expected.size());
3909 }
3910
3911 void tst_QJSValue::engineDeleted()
3912 {
3913     QJSEngine *eng = new QJSEngine;
3914     QJSValue v1(eng, 123);
3915     QVERIFY(v1.isNumber());
3916     QJSValue v2(eng, QString("ciao"));
3917     QVERIFY(v2.isString());
3918     QJSValue v3 = eng->newObject();
3919     QVERIFY(v3.isObject());
3920     QJSValue v4 = eng->newQObject(this);
3921     QVERIFY(v4.isQObject());
3922     QJSValue v5 = "Hello";
3923     QVERIFY(v2.isString());
3924
3925     delete eng;
3926
3927     QVERIFY(!v1.isValid());
3928     QVERIFY(v1.engine() == 0);
3929     QVERIFY(!v2.isValid());
3930     QVERIFY(v2.engine() == 0);
3931     QVERIFY(!v3.isValid());
3932     QVERIFY(v3.engine() == 0);
3933     QVERIFY(!v4.isValid());
3934     QVERIFY(v4.engine() == 0);
3935     QVERIFY(v5.isValid());
3936     QVERIFY(v5.engine() == 0);
3937
3938     QVERIFY(!v3.property("foo").isValid());
3939 }
3940
3941 void tst_QJSValue::valueOfWithClosure()
3942 {
3943     QJSEngine eng;
3944     // valueOf()
3945     {
3946         QJSValue obj = eng.evaluate("o = {}; (function(foo) { o.valueOf = function() { return foo; } })(123); o");
3947         QVERIFY(obj.isObject());
3948         QCOMPARE(obj.toInt32(), 123);
3949     }
3950     // toString()
3951     {
3952         QJSValue obj = eng.evaluate("o = {}; (function(foo) { o.toString = function() { return foo; } })('ciao'); o");
3953         QVERIFY(obj.isObject());
3954         QCOMPARE(obj.toString(), QString::fromLatin1("ciao"));
3955     }
3956 }
3957
3958 #if 0 // FIXME: no objectId()
3959 void tst_QJSValue::objectId()
3960 {
3961     QCOMPARE(QJSValue().objectId(), (qint64)-1);
3962     QCOMPARE(QJSValue(QJSValue::UndefinedValue).objectId(), (qint64)-1);
3963     QCOMPARE(QJSValue(QJSValue::NullValue).objectId(), (qint64)-1);
3964     QCOMPARE(QJSValue(false).objectId(), (qint64)-1);
3965     QCOMPARE(QJSValue(123).objectId(), (qint64)-1);
3966     QCOMPARE(QJSValue(uint(123)).objectId(), (qint64)-1);
3967     QCOMPARE(QJSValue(123.5).objectId(), (qint64)-1);
3968     QCOMPARE(QJSValue("ciao").objectId(), (qint64)-1);
3969
3970     QScriptEngine eng;
3971     QJSValue o1 = eng.newObject();
3972     QVERIFY(o1.objectId() != -1);
3973     QJSValue o2 = eng.newObject();
3974     QVERIFY(o2.objectId() != -1);
3975     QVERIFY(o1.objectId() != o2.objectId());
3976
3977     QVERIFY(eng.objectById(o1.objectId()).strictlyEquals(o1));
3978     QVERIFY(eng.objectById(o2.objectId()).strictlyEquals(o2));
3979
3980     qint64 globalObjectId = -1;
3981     {
3982         QJSValue global = eng.globalObject();
3983         globalObjectId = global.objectId();
3984         QVERIFY(globalObjectId != -1);
3985         QVERIFY(eng.objectById(globalObjectId).strictlyEquals(global));
3986     }
3987     QJSValue obj = eng.objectById(globalObjectId);
3988     QVERIFY(obj.isObject());
3989     QVERIFY(obj.strictlyEquals(eng.globalObject()));
3990 }
3991 #endif
3992
3993 void tst_QJSValue::nestedObjectToVariant_data()
3994 {
3995     QTest::addColumn<QString>("program");
3996     QTest::addColumn<QVariant>("expected");
3997
3998     // Array literals
3999     QTest::newRow("[[]]")
4000         << QString::fromLatin1("[[]]")
4001         << QVariant(QVariantList() << (QVariant(QVariantList())));
4002     QTest::newRow("[[123]]")
4003         << QString::fromLatin1("[[123]]")
4004         << QVariant(QVariantList() << (QVariant(QVariantList() << 123)));
4005     QTest::newRow("[[], 123]")
4006         << QString::fromLatin1("[[], 123]")
4007         << QVariant(QVariantList() << QVariant(QVariantList()) << 123);
4008
4009     // Cyclic arrays
4010     QTest::newRow("var a=[]; a.push(a)")
4011         << QString::fromLatin1("var a=[]; a.push(a); a")
4012         << QVariant(QVariantList() << QVariant(QVariantList()));
4013     QTest::newRow("var a=[]; a.push(123, a)")
4014         << QString::fromLatin1("var a=[]; a.push(123, a); a")
4015         << QVariant(QVariantList() << 123 << QVariant(QVariantList()));
4016     QTest::newRow("var a=[]; var b=[]; a.push(b); b.push(a)")
4017         << QString::fromLatin1("var a=[]; var b=[]; a.push(b); b.push(a); a")
4018         << QVariant(QVariantList() << QVariant(QVariantList() << QVariant(QVariantList())));
4019     QTest::newRow("var a=[]; var b=[]; a.push(123, b); b.push(456, a)")
4020         << QString::fromLatin1("var a=[]; var b=[]; a.push(123, b); b.push(456, a); a")
4021         << QVariant(QVariantList() << 123 << QVariant(QVariantList() << 456 << QVariant(QVariantList())));
4022
4023     // Object literals
4024     {
4025         QVariantMap m;
4026         m["a"] = QVariantMap();
4027         QTest::newRow("{ a:{} }")
4028             << QString::fromLatin1("({ a:{} })")
4029             << QVariant(m);
4030     }
4031     {
4032         QVariantMap m, m2;
4033         m2["b"] = 10;
4034         m2["c"] = 20;
4035         m["a"] = m2;
4036         QTest::newRow("{ a:{b:10, c:20} }")
4037             << QString::fromLatin1("({ a:{b:10, c:20} })")
4038             << QVariant(m);
4039     }
4040     {
4041         QVariantMap m;
4042         m["a"] = 10;
4043         m["b"] = QVariantList() << 20 << 30;
4044         QTest::newRow("{ a:10, b:[20, 30]}")
4045             << QString::fromLatin1("({ a:10, b:[20,30]})")
4046             << QVariant(m);
4047     }
4048
4049     // Cyclic objects
4050     {
4051         QVariantMap m;
4052         m["p"] = QVariantMap();
4053         QTest::newRow("var o={}; o.p=o")
4054             << QString::fromLatin1("var o={}; o.p=o; o")
4055             << QVariant(m);
4056     }
4057     {
4058         QVariantMap m;
4059         m["p"] = 123;
4060         m["q"] = QVariantMap();
4061         QTest::newRow("var o={}; o.p=123; o.q=o")
4062             << QString::fromLatin1("var o={}; o.p=123; o.q=o; o")
4063             << QVariant(m);
4064     }
4065 }
4066
4067 void tst_QJSValue::nestedObjectToVariant()
4068 {
4069     QJSEngine eng;
4070     QFETCH(QString, program);
4071     QFETCH(QVariant, expected);
4072     QJSValue o = eng.evaluate(program);
4073     QVERIFY(!o.isError());
4074     QVERIFY(o.isObject());
4075     QCOMPARE(o.toVariant(), expected);
4076 }
4077
4078 void tst_QJSValue::propertyFlags_data()
4079 {
4080     QTest::addColumn<QString>("program");
4081     QTest::addColumn<uint>("expected");
4082
4083     QTest::newRow("nothing") << "" << 0u;
4084 #if 0 // FIXME: No getter/setter API
4085     QTest::newRow("getter") << "o.__defineGetter__('prop', function() { return 'blah' } );\n" << uint(QJSValue::PropertyGetter);
4086     QTest::newRow("setter") << "o.__defineSetter__('prop', function(a) { this.setted_prop2 = a; } );\n" << uint(QJSValue::PropertySetter);
4087     QTest::newRow("getterSetter") <<  "o.__defineGetter__('prop', function() { return 'ploup' } );\n"
4088                                       "o.__defineSetter__('prop', function(a) { this.setted_prop3 = a; } );\n" << uint(QJSValue::PropertySetter|QJSValue::PropertyGetter);
4089 #endif
4090     QTest::newRow("nothing2") << "o.prop = 'nothing'" << 0u;
4091 }
4092
4093 void tst_QJSValue::propertyFlags()
4094 {
4095     QFETCH(QString, program);
4096     QFETCH(uint, expected);
4097     QJSEngine eng;
4098     eng.evaluate("o = new Object;");
4099     eng.evaluate(program);
4100     QJSValue o = eng.evaluate("o");
4101
4102     QCOMPARE(uint(o.propertyFlags("prop")), expected);
4103 }
4104
4105
4106 QTEST_MAIN(tst_QJSValue)