52e47732ae9bd1e5b258f76c92f8efd5585e5b1f
[profile/ivi/qtdeclarative.git] / tests / auto / declarative / qjsvalue / tst_qjsvalue.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: http://www.qt-project.org/
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.isBool(), true);
101         QCOMPARE(v.isBool(), true);
102         QCOMPARE(v.isObject(), false);
103         QCOMPARE(v.toBool(), 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.toInt(), 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.toUInt(), 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.isBool(), true);
287     QCOMPARE(v.isBool(), true);
288     QCOMPARE(v.isObject(), false);
289     QCOMPARE(v.toBool(), 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.toBool(), false);
540     QCOMPARE(qjsvalue_cast<bool>(undefined), false);
541
542     QJSValue null = eng.nullValue();
543     QCOMPARE(null.toBool(), false);
544     QCOMPARE(qjsvalue_cast<bool>(null), false);
545
546     {
547         QJSValue falskt = QJSValue(&eng, false);
548         QCOMPARE(falskt.toBool(), false);
549         QCOMPARE(qjsvalue_cast<bool>(falskt), false);
550
551         QJSValue sant = QJSValue(&eng, true);
552         QCOMPARE(sant.toBool(), true);
553         QCOMPARE(qjsvalue_cast<bool>(sant), true);
554
555         QJSValue number = QJSValue(&eng, 0.0);
556         QCOMPARE(number.toBool(), false);
557         QCOMPARE(qjsvalue_cast<bool>(number), false);
558
559         QJSValue number2 = QJSValue(&eng, qSNaN());
560         QCOMPARE(number2.toBool(), false);
561         QCOMPARE(qjsvalue_cast<bool>(number2), false);
562
563         QJSValue number3 = QJSValue(&eng, 123.0);
564         QCOMPARE(number3.toBool(), true);
565         QCOMPARE(qjsvalue_cast<bool>(number3), true);
566
567         QJSValue number4 = QJSValue(&eng, -456.0);
568         QCOMPARE(number4.toBool(), true);
569         QCOMPARE(qjsvalue_cast<bool>(number4), true);
570
571         QJSValue str = QJSValue(&eng, QString(""));
572         QCOMPARE(str.toBool(), false);
573         QCOMPARE(qjsvalue_cast<bool>(str), false);
574
575         QJSValue str2 = QJSValue(&eng, QString("123"));
576         QCOMPARE(str2.toBool(), true);
577         QCOMPARE(qjsvalue_cast<bool>(str2), true);
578     }
579
580     QJSValue object = eng.newObject();
581     QCOMPARE(object.toBool(), 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.toBool(), false);
593     QCOMPARE(qjsvalue_cast<bool>(inv), false);
594
595     // V2 constructors
596     {
597         QJSValue falskt = QJSValue(false);
598         QCOMPARE(falskt.toBool(), false);
599         QCOMPARE(qjsvalue_cast<bool>(falskt), false);
600
601         QJSValue sant = QJSValue(true);
602         QCOMPARE(sant.toBool(), true);
603         QCOMPARE(qjsvalue_cast<bool>(sant), true);
604
605         QJSValue number = QJSValue(0.0);
606         QCOMPARE(number.toBool(), false);
607         QCOMPARE(qjsvalue_cast<bool>(number), false);
608
609         QJSValue number2 = QJSValue(qSNaN());
610         QCOMPARE(number2.toBool(), false);
611         QCOMPARE(qjsvalue_cast<bool>(number2), false);
612
613         QJSValue number3 = QJSValue(123.0);
614         QCOMPARE(number3.toBool(), true);
615         QCOMPARE(qjsvalue_cast<bool>(number3), true);
616
617         QJSValue number4 = QJSValue(-456.0);
618         QCOMPARE(number4.toBool(), true);
619         QCOMPARE(qjsvalue_cast<bool>(number4), true);
620
621         QJSValue number5 = QJSValue(0x43211234);
622         QCOMPARE(number5.toBool(), true);
623
624         QJSValue str = QJSValue(QString(""));
625         QCOMPARE(str.toBool(), false);
626         QCOMPARE(qjsvalue_cast<bool>(str), false);
627
628         QJSValue str2 = QJSValue(QString("123"));
629         QCOMPARE(str2.toBool(), 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::toInt()
822 {
823     QJSEngine eng;
824
825     {
826         QJSValue zer0 = QJSValue(&eng, 0.0);
827         QCOMPARE(zer0.toInt(), 0);
828         QCOMPARE(qjsvalue_cast<qint32>(zer0), 0);
829
830         QJSValue number = QJSValue(&eng, 123.0);
831         QCOMPARE(number.toInt(), 123);
832         QCOMPARE(qjsvalue_cast<qint32>(number), 123);
833
834         QJSValue number2 = QJSValue(&eng, qSNaN());
835         QCOMPARE(number2.toInt(), 0);
836         QCOMPARE(qjsvalue_cast<qint32>(number2), 0);
837
838         QJSValue number3 = QJSValue(&eng, +qInf());
839         QCOMPARE(number3.toInt(), 0);
840         QCOMPARE(qjsvalue_cast<qint32>(number3), 0);
841
842         QJSValue number3_2 = QJSValue(&eng, -qInf());
843         QCOMPARE(number3_2.toInt(), 0);
844         QCOMPARE(qjsvalue_cast<qint32>(number3_2), 0);
845
846         QJSValue number4 = QJSValue(&eng, 0.5);
847         QCOMPARE(number4.toInt(), 0);
848         QCOMPARE(qjsvalue_cast<qint32>(number4), 0);
849
850         QJSValue number5 = QJSValue(&eng, 123.5);
851         QCOMPARE(number5.toInt(), 123);
852         QCOMPARE(qjsvalue_cast<qint32>(number5), 123);
853
854         QJSValue number6 = QJSValue(&eng, -456.5);
855         QCOMPARE(number6.toInt(), -456);
856         QCOMPARE(qjsvalue_cast<qint32>(number6), -456);
857
858         QJSValue str = QJSValue(&eng, QLatin1String("123.0"));
859         QCOMPARE(str.toInt(), 123);
860         QCOMPARE(qjsvalue_cast<qint32>(str), 123);
861
862         QJSValue str2 = QJSValue(&eng, QLatin1String("NaN"));
863         QCOMPARE(str2.toInt(), 0);
864         QCOMPARE(qjsvalue_cast<qint32>(str2), 0);
865
866         QJSValue str3 = QJSValue(&eng, QLatin1String("Infinity"));
867         QCOMPARE(str3.toInt(), 0);
868         QCOMPARE(qjsvalue_cast<qint32>(str3), 0);
869
870         QJSValue str3_2 = QJSValue(&eng, QLatin1String("-Infinity"));
871         QCOMPARE(str3_2.toInt(), 0);
872         QCOMPARE(qjsvalue_cast<qint32>(str3_2), 0);
873
874         QJSValue str4 = QJSValue(&eng, QLatin1String("0.5"));
875         QCOMPARE(str4.toInt(), 0);
876         QCOMPARE(qjsvalue_cast<qint32>(str4), 0);
877
878         QJSValue str5 = QJSValue(&eng, QLatin1String("123.5"));
879         QCOMPARE(str5.toInt(), 123);
880         QCOMPARE(qjsvalue_cast<qint32>(str5), 123);
881
882         QJSValue str6 = QJSValue(&eng, QLatin1String("-456.5"));
883         QCOMPARE(str6.toInt(), -456);
884         QCOMPARE(qjsvalue_cast<qint32>(str6), -456);
885     }
886     // V2 constructors
887     {
888         QJSValue zer0 = QJSValue(0.0);
889         QCOMPARE(zer0.toInt(), 0);
890         QCOMPARE(qjsvalue_cast<qint32>(zer0), 0);
891
892         QJSValue number = QJSValue(123.0);
893         QCOMPARE(number.toInt(), 123);
894         QCOMPARE(qjsvalue_cast<qint32>(number), 123);
895
896         QJSValue number2 = QJSValue(qSNaN());
897         QCOMPARE(number2.toInt(), 0);
898         QCOMPARE(qjsvalue_cast<qint32>(number2), 0);
899
900         QJSValue number3 = QJSValue(+qInf());
901         QCOMPARE(number3.toInt(), 0);
902         QCOMPARE(qjsvalue_cast<qint32>(number3), 0);
903
904         QJSValue number3_2 = QJSValue(-qInf());
905         QCOMPARE(number3_2.toInt(), 0);
906         QCOMPARE(qjsvalue_cast<qint32>(number3_2), 0);
907
908         QJSValue number4 = QJSValue(0.5);
909         QCOMPARE(number4.toInt(), 0);
910         QCOMPARE(qjsvalue_cast<qint32>(number4), 0);
911
912         QJSValue number5 = QJSValue(123.5);
913         QCOMPARE(number5.toInt(), 123);
914         QCOMPARE(qjsvalue_cast<qint32>(number5), 123);
915
916         QJSValue number6 = QJSValue(-456.5);
917         QCOMPARE(number6.toInt(), -456);
918         QCOMPARE(qjsvalue_cast<qint32>(number6), -456);
919
920         QJSValue number7 = QJSValue(0x43211234);
921         QCOMPARE(number7.toInt(), 0x43211234);
922
923         QJSValue str = QJSValue("123.0");
924         QCOMPARE(str.toInt(), 123);
925         QCOMPARE(qjsvalue_cast<qint32>(str), 123);
926
927         QJSValue str2 = QJSValue("NaN");
928         QCOMPARE(str2.toInt(), 0);
929         QCOMPARE(qjsvalue_cast<qint32>(str2), 0);
930
931         QJSValue str3 = QJSValue("Infinity");
932         QCOMPARE(str3.toInt(), 0);
933         QCOMPARE(qjsvalue_cast<qint32>(str3), 0);
934
935         QJSValue str3_2 = QJSValue("-Infinity");
936         QCOMPARE(str3_2.toInt(), 0);
937         QCOMPARE(qjsvalue_cast<qint32>(str3_2), 0);
938
939         QJSValue str4 = QJSValue("0.5");
940         QCOMPARE(str4.toInt(), 0);
941         QCOMPARE(qjsvalue_cast<qint32>(str4), 0);
942
943         QJSValue str5 = QJSValue("123.5");
944         QCOMPARE(str5.toInt(), 123);
945         QCOMPARE(qjsvalue_cast<qint32>(str5), 123);
946
947         QJSValue str6 = QJSValue("-456.5");
948         QCOMPARE(str6.toInt(), -456);
949         QCOMPARE(qjsvalue_cast<qint32>(str6), -456);
950     }
951
952     QJSValue inv;
953     QCOMPARE(inv.toInt(), 0);
954     QCOMPARE(qjsvalue_cast<qint32>(inv), 0);
955 }
956
957 void tst_QJSValue::toUInt()
958 {
959     QJSEngine eng;
960
961     {
962         QJSValue zer0 = eng.toScriptValue(0.0);
963         QCOMPARE(zer0.toUInt(), quint32(0));
964         QCOMPARE(qjsvalue_cast<quint32>(zer0), quint32(0));
965
966         QJSValue number = eng.toScriptValue(123.0);
967         QCOMPARE(number.toUInt(), quint32(123));
968         QCOMPARE(qjsvalue_cast<quint32>(number), quint32(123));
969
970         QJSValue number2 = eng.toScriptValue(qSNaN());
971         QCOMPARE(number2.toUInt(), quint32(0));
972         QCOMPARE(qjsvalue_cast<quint32>(number2), quint32(0));
973
974         QJSValue number3 = eng.toScriptValue(+qInf());
975         QCOMPARE(number3.toUInt(), quint32(0));
976         QCOMPARE(qjsvalue_cast<quint32>(number3), quint32(0));
977
978         QJSValue number3_2 = eng.toScriptValue(-qInf());
979         QCOMPARE(number3_2.toUInt(), quint32(0));
980         QCOMPARE(qjsvalue_cast<quint32>(number3_2), quint32(0));
981
982         QJSValue number4 = eng.toScriptValue(0.5);
983         QCOMPARE(number4.toUInt(), quint32(0));
984
985         QJSValue number5 = eng.toScriptValue(123.5);
986         QCOMPARE(number5.toUInt(), quint32(123));
987
988         QJSValue number6 = eng.toScriptValue(-456.5);
989         QCOMPARE(number6.toUInt(), quint32(-456));
990         QCOMPARE(qjsvalue_cast<quint32>(number6), quint32(-456));
991
992         QJSValue str = eng.toScriptValue(QString::fromLatin1("123.0"));
993         QCOMPARE(str.toUInt(), quint32(123));
994         QCOMPARE(qjsvalue_cast<quint32>(str), quint32(123));
995
996         QJSValue str2 = eng.toScriptValue(QString::fromLatin1("NaN"));
997         QCOMPARE(str2.toUInt(), quint32(0));
998         QCOMPARE(qjsvalue_cast<quint32>(str2), quint32(0));
999
1000         QJSValue str3 = eng.toScriptValue(QString::fromLatin1("Infinity"));
1001         QCOMPARE(str3.toUInt(), quint32(0));
1002         QCOMPARE(qjsvalue_cast<quint32>(str3), quint32(0));
1003
1004         QJSValue str3_2 = eng.toScriptValue(QString::fromLatin1("-Infinity"));
1005         QCOMPARE(str3_2.toUInt(), quint32(0));
1006         QCOMPARE(qjsvalue_cast<quint32>(str3_2), quint32(0));
1007
1008         QJSValue str4 = eng.toScriptValue(QString::fromLatin1("0.5"));
1009         QCOMPARE(str4.toUInt(), quint32(0));
1010         QCOMPARE(qjsvalue_cast<quint32>(str4), quint32(0));
1011
1012         QJSValue str5 = eng.toScriptValue(QString::fromLatin1("123.5"));
1013         QCOMPARE(str5.toUInt(), quint32(123));
1014         QCOMPARE(qjsvalue_cast<quint32>(str5), quint32(123));
1015
1016         QJSValue str6 = eng.toScriptValue(QString::fromLatin1("-456.5"));
1017         QCOMPARE(str6.toUInt(), quint32(-456));
1018         QCOMPARE(qjsvalue_cast<quint32>(str6), quint32(-456));
1019     }
1020     // V2 constructors
1021     {
1022         QJSValue zer0 = QJSValue(0.0);
1023         QCOMPARE(zer0.toUInt(), quint32(0));
1024         QCOMPARE(qjsvalue_cast<quint32>(zer0), quint32(0));
1025
1026         QJSValue number = QJSValue(123.0);
1027         QCOMPARE(number.toUInt(), quint32(123));
1028         QCOMPARE(qjsvalue_cast<quint32>(number), quint32(123));
1029
1030         QJSValue number2 = QJSValue(qSNaN());
1031         QCOMPARE(number2.toUInt(), quint32(0));
1032         QCOMPARE(qjsvalue_cast<quint32>(number2), quint32(0));
1033
1034         QJSValue number3 = QJSValue(+qInf());
1035         QCOMPARE(number3.toUInt(), quint32(0));
1036         QCOMPARE(qjsvalue_cast<quint32>(number3), quint32(0));
1037
1038         QJSValue number3_2 = QJSValue(-qInf());
1039         QCOMPARE(number3_2.toUInt(), quint32(0));
1040         QCOMPARE(qjsvalue_cast<quint32>(number3_2), quint32(0));
1041
1042         QJSValue number4 = QJSValue(0.5);
1043         QCOMPARE(number4.toUInt(), quint32(0));
1044
1045         QJSValue number5 = QJSValue(123.5);
1046         QCOMPARE(number5.toUInt(), quint32(123));
1047
1048         QJSValue number6 = QJSValue(-456.5);
1049         QCOMPARE(number6.toUInt(), quint32(-456));
1050         QCOMPARE(qjsvalue_cast<quint32>(number6), quint32(-456));
1051
1052         QJSValue number7 = QJSValue(0x43211234);
1053         QCOMPARE(number7.toUInt(), quint32(0x43211234));
1054
1055         QJSValue str = QJSValue(QLatin1String("123.0"));
1056         QCOMPARE(str.toUInt(), quint32(123));
1057         QCOMPARE(qjsvalue_cast<quint32>(str), quint32(123));
1058
1059         QJSValue str2 = QJSValue(QLatin1String("NaN"));
1060         QCOMPARE(str2.toUInt(), quint32(0));
1061         QCOMPARE(qjsvalue_cast<quint32>(str2), quint32(0));
1062
1063         QJSValue str3 = QJSValue(QLatin1String("Infinity"));
1064         QCOMPARE(str3.toUInt(), quint32(0));
1065         QCOMPARE(qjsvalue_cast<quint32>(str3), quint32(0));
1066
1067         QJSValue str3_2 = QJSValue(QLatin1String("-Infinity"));
1068         QCOMPARE(str3_2.toUInt(), quint32(0));
1069         QCOMPARE(qjsvalue_cast<quint32>(str3_2), quint32(0));
1070
1071         QJSValue str4 = QJSValue(QLatin1String("0.5"));
1072         QCOMPARE(str4.toUInt(), quint32(0));
1073         QCOMPARE(qjsvalue_cast<quint32>(str4), quint32(0));
1074
1075         QJSValue str5 = QJSValue(QLatin1String("123.5"));
1076         QCOMPARE(str5.toUInt(), quint32(123));
1077         QCOMPARE(qjsvalue_cast<quint32>(str5), quint32(123));
1078
1079         QJSValue str6 = QJSValue(QLatin1String("-456.5"));
1080         QCOMPARE(str6.toUInt(), quint32(-456));
1081         QCOMPARE(qjsvalue_cast<quint32>(str6), quint32(-456));
1082     }
1083
1084     QJSValue inv;
1085     QCOMPARE(inv.toUInt(), 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").toInt(), 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").toInt(), array.property("length").toInt());
1354         for (int i = 0; i < array.property("length").toInt(); ++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.toInt(), number.toInt());
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.isCallable());
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::hasProperty_basic()
1796 {
1797     QJSEngine eng;
1798     QJSValue obj = eng.newObject();
1799     QVERIFY(obj.hasProperty("hasOwnProperty")); // inherited from Object.prototype
1800     QVERIFY(!obj.hasOwnProperty("hasOwnProperty"));
1801
1802     QVERIFY(!obj.hasProperty("foo"));
1803     QVERIFY(!obj.hasOwnProperty("foo"));
1804     obj.setProperty("foo", 123);
1805     QVERIFY(obj.hasProperty("foo"));
1806     QVERIFY(obj.hasOwnProperty("foo"));
1807
1808     QVERIFY(!obj.hasProperty("bar"));
1809     QVERIFY(!obj.hasOwnProperty("bar"));
1810 }
1811
1812 void tst_QJSValue::hasProperty_globalObject()
1813 {
1814     QJSEngine eng;
1815     QJSValue global = eng.globalObject();
1816     QVERIFY(global.hasProperty("Math"));
1817     QVERIFY(global.hasOwnProperty("Math"));
1818     QVERIFY(!global.hasProperty("NoSuchStandardProperty"));
1819     QVERIFY(!global.hasOwnProperty("NoSuchStandardProperty"));
1820
1821     QVERIFY(!global.hasProperty("foo"));
1822     QVERIFY(!global.hasOwnProperty("foo"));
1823     global.setProperty("foo", 123);
1824     QVERIFY(global.hasProperty("foo"));
1825     QVERIFY(global.hasOwnProperty("foo"));
1826 }
1827
1828 void tst_QJSValue::hasProperty_changePrototype()
1829 {
1830     QJSEngine eng;
1831     QJSValue obj = eng.newObject();
1832     QJSValue proto = eng.newObject();
1833     obj.setPrototype(proto);
1834
1835     QVERIFY(!obj.hasProperty("foo"));
1836     QVERIFY(!obj.hasOwnProperty("foo"));
1837     proto.setProperty("foo", 123);
1838     QVERIFY(obj.hasProperty("foo"));
1839     QVERIFY(!obj.hasOwnProperty("foo"));
1840
1841     obj.setProperty("foo", 456); // override prototype property
1842     QVERIFY(obj.hasProperty("foo"));
1843     QVERIFY(obj.hasOwnProperty("foo"));
1844 }
1845
1846 void tst_QJSValue::deleteProperty_basic()
1847 {
1848     QJSEngine eng;
1849     QJSValue obj = eng.newObject();
1850     // deleteProperty() behavior matches JS delete operator
1851     QVERIFY(obj.deleteProperty("foo"));
1852
1853     obj.setProperty("foo", 123);
1854     QVERIFY(obj.deleteProperty("foo"));
1855     QVERIFY(!obj.hasOwnProperty("foo"));
1856 }
1857
1858 void tst_QJSValue::deleteProperty_globalObject()
1859 {
1860     QJSEngine eng;
1861     QJSValue global = eng.globalObject();
1862     // deleteProperty() behavior matches JS delete operator
1863     QVERIFY(global.deleteProperty("foo"));
1864
1865     global.setProperty("foo", 123);
1866     QVERIFY(global.deleteProperty("foo"));
1867     QVERIFY(!global.hasProperty("foo"));
1868
1869     QVERIFY(global.deleteProperty("Math"));
1870     QVERIFY(!global.hasProperty("Math"));
1871
1872     QVERIFY(!global.deleteProperty("NaN")); // read-only
1873     QVERIFY(global.hasProperty("NaN"));
1874 }
1875
1876 void tst_QJSValue::deleteProperty_inPrototype()
1877 {
1878     QJSEngine eng;
1879     QJSValue obj = eng.newObject();
1880     QJSValue proto = eng.newObject();
1881     obj.setPrototype(proto);
1882
1883     proto.setProperty("foo", 123);
1884     QVERIFY(obj.hasProperty("foo"));
1885     // deleteProperty() behavior matches JS delete operator
1886     QVERIFY(obj.deleteProperty("foo"));
1887     QVERIFY(obj.hasProperty("foo"));
1888 }
1889
1890 void tst_QJSValue::getSetProperty_HooliganTask162051()
1891 {
1892     QJSEngine eng;
1893     // task 162051 -- detecting whether the property is an array index or not
1894     QVERIFY(eng.evaluate("a = []; a['00'] = 123; a['00']").strictlyEquals(QJSValue(&eng, 123)));
1895     QVERIFY(eng.evaluate("a.length").strictlyEquals(QJSValue(&eng, 0)));
1896     QVERIFY(eng.evaluate("a.hasOwnProperty('00')").strictlyEquals(QJSValue(&eng, true)));
1897     QVERIFY(eng.evaluate("a.hasOwnProperty('0')").strictlyEquals(QJSValue(&eng, false)));
1898     QVERIFY(eng.evaluate("a[0]").isUndefined());
1899     QVERIFY(eng.evaluate("a[0.5] = 456; a[0.5]").strictlyEquals(QJSValue(&eng, 456)));
1900     QVERIFY(eng.evaluate("a.length").strictlyEquals(QJSValue(&eng, 0)));
1901     QVERIFY(eng.evaluate("a.hasOwnProperty('0.5')").strictlyEquals(QJSValue(&eng, true)));
1902     QVERIFY(eng.evaluate("a[0]").isUndefined());
1903     QVERIFY(eng.evaluate("a[0] = 789; a[0]").strictlyEquals(QJSValue(&eng, 789)));
1904     QVERIFY(eng.evaluate("a.length").strictlyEquals(QJSValue(&eng, 1)));
1905 }
1906
1907 void tst_QJSValue::getSetProperty_HooliganTask183072()
1908 {
1909     QJSEngine eng;
1910     // task 183072 -- 0x800000000 is not an array index
1911     eng.evaluate("a = []; a[0x800000000] = 123");
1912     QVERIFY(eng.evaluate("a.length").strictlyEquals(QJSValue(&eng, 0)));
1913     QVERIFY(eng.evaluate("a[0]").isUndefined());
1914     QVERIFY(eng.evaluate("a[0x800000000]").strictlyEquals(QJSValue(&eng, 123)));
1915 }
1916
1917 void tst_QJSValue::getSetProperty_propertyRemoval()
1918 {
1919     // test property removal (setProperty(QJSValue()))
1920     QJSEngine eng;
1921     QJSValue object = eng.newObject();
1922     QJSValue str = QJSValue(&eng, QLatin1String("bar"));
1923     QJSValue num = QJSValue(&eng, 123.0);
1924
1925     object.setProperty("foo", num);
1926     QCOMPARE(object.property("foo").strictlyEquals(num), true);
1927     object.setProperty("bar", str);
1928     QCOMPARE(object.property("bar").strictlyEquals(str), true);
1929     object.setProperty("foo", QJSValue());
1930     QCOMPARE(object.property("foo").isValid(), false);
1931     QCOMPARE(object.property("bar").strictlyEquals(str), true);
1932     object.setProperty("foo", num);
1933     QCOMPARE(object.property("foo").strictlyEquals(num), true);
1934     QCOMPARE(object.property("bar").strictlyEquals(str), true);
1935     object.setProperty("bar", QJSValue());
1936     QCOMPARE(object.property("bar").isValid(), false);
1937     QCOMPARE(object.property("foo").strictlyEquals(num), true);
1938     object.setProperty("foo", QJSValue());
1939     object.setProperty("foo", QJSValue());
1940
1941     eng.globalObject().setProperty("object3", object);
1942     QCOMPARE(eng.evaluate("object3.hasOwnProperty('foo')")
1943              .strictlyEquals(QJSValue(&eng, false)), true);
1944     object.setProperty("foo", num);
1945     QCOMPARE(eng.evaluate("object3.hasOwnProperty('foo')")
1946              .strictlyEquals(QJSValue(&eng, true)), true);
1947     eng.globalObject().setProperty("object3", QJSValue());
1948     QCOMPARE(eng.evaluate("this.hasOwnProperty('object3')")
1949              .strictlyEquals(QJSValue(&eng, false)), true);
1950 }
1951
1952 void tst_QJSValue::getSetProperty_resolveMode()
1953 {
1954     // test ResolveMode
1955     QJSEngine eng;
1956     QJSValue object = eng.newObject();
1957     QJSValue prototype = eng.newObject();
1958     object.setPrototype(prototype);
1959     QJSValue num2 = QJSValue(&eng, 456.0);
1960     prototype.setProperty("propertyInPrototype", num2);
1961     // default is ResolvePrototype
1962     QCOMPARE(object.property("propertyInPrototype")
1963              .strictlyEquals(num2), true);
1964 #if 0 // FIXME: ResolveFlags removed from API
1965     QCOMPARE(object.property("propertyInPrototype", QJSValue::ResolvePrototype)
1966              .strictlyEquals(num2), true);
1967     QCOMPARE(object.property("propertyInPrototype", QJSValue::ResolveLocal)
1968              .isValid(), false);
1969     QCOMPARE(object.property("propertyInPrototype", QJSValue::ResolveScope)
1970              .strictlyEquals(num2), false);
1971     QCOMPARE(object.property("propertyInPrototype", QJSValue::ResolveFull)
1972              .strictlyEquals(num2), true);
1973 #endif
1974 }
1975
1976 void tst_QJSValue::getSetProperty_twoEngines()
1977 {
1978     QJSEngine engine;
1979     QJSValue object = engine.newObject();
1980
1981     QJSEngine otherEngine;
1982     QJSValue otherNum = QJSValue(&otherEngine, 123);
1983     QTest::ignoreMessage(QtWarningMsg, "QJSValue::setProperty(oof) failed: cannot set value created in a different engine");
1984     object.setProperty("oof", otherNum);
1985     QCOMPARE(object.property("oof").isValid(), false);
1986 }
1987
1988
1989 void tst_QJSValue::getSetProperty_gettersAndSetters()
1990 {
1991 #if 0 // FIXME: No setters/getters right now
1992     QScriptEngine eng;
1993     QJSValue str = QJSValue(&eng, QLatin1String("bar"));
1994     QJSValue num = QJSValue(&eng, 123.0);
1995     QJSValue object = eng.newObject();
1996     for (int x = 0; x < 2; ++x) {
1997         object.setProperty("foo", QJSValue());
1998         // getter() returns this.x
1999         object.setProperty("foo", eng.newFunction(getter),
2000                             QJSValue::PropertyGetter | QJSValue::UserRange);
2001         QCOMPARE(object.propertyFlags("foo") & ~QJSValue::UserRange,
2002                  QJSValue::PropertyGetter );
2003
2004         QEXPECT_FAIL("", "QTBUG-17615: User-range flags are not retained for getter/setter properties", Continue);
2005         QCOMPARE(object.propertyFlags("foo"),
2006                  QJSValue::PropertyGetter | QJSValue::UserRange);
2007         object.setProperty("x", num);
2008         QCOMPARE(object.property("foo").strictlyEquals(num), true);
2009
2010         // setter() sets this.x
2011         object.setProperty("foo", eng.newFunction(setter),
2012                             QJSValue::PropertySetter);
2013         QCOMPARE(object.propertyFlags("foo") & ~QJSValue::UserRange,
2014                  QJSValue::PropertySetter | QJSValue::PropertyGetter);
2015
2016         QCOMPARE(object.propertyFlags("foo"),
2017                  QJSValue::PropertySetter | QJSValue::PropertyGetter);
2018         object.setProperty("foo", str);
2019         QCOMPARE(object.property("x").strictlyEquals(str), true);
2020         QCOMPARE(object.property("foo").strictlyEquals(str), true);
2021
2022         // kill the getter
2023         object.setProperty("foo", QJSValue(), QJSValue::PropertyGetter);
2024         QVERIFY(!(object.propertyFlags("foo") & QJSValue::PropertyGetter));
2025         QVERIFY(object.propertyFlags("foo") & QJSValue::PropertySetter);
2026         QCOMPARE(object.property("foo").isUndefined(), true);
2027
2028         // setter should still work
2029         object.setProperty("foo", num);
2030         QCOMPARE(object.property("x").strictlyEquals(num), true);
2031
2032         // kill the setter too
2033         object.setProperty("foo", QJSValue(), QJSValue::PropertySetter);
2034         QVERIFY(!(object.propertyFlags("foo") & QJSValue::PropertySetter));
2035         // now foo is just a regular property
2036         object.setProperty("foo", str);
2037         QCOMPARE(object.property("x").strictlyEquals(num), true);
2038         QCOMPARE(object.property("foo").strictlyEquals(str), true);
2039     }
2040
2041     for (int x = 0; x < 2; ++x) {
2042         object.setProperty("foo", QJSValue());
2043         // setter() sets this.x
2044         object.setProperty("foo", eng.newFunction(setter), QJSValue::PropertySetter);
2045         object.setProperty("foo", str);
2046         QCOMPARE(object.property("x").strictlyEquals(str), true);
2047         QCOMPARE(object.property("foo").isUndefined(), true);
2048
2049         // getter() returns this.x
2050         object.setProperty("foo", eng.newFunction(getter), QJSValue::PropertyGetter);
2051         object.setProperty("x", num);
2052         QCOMPARE(object.property("foo").strictlyEquals(num), true);
2053
2054         // kill the setter
2055         object.setProperty("foo", QJSValue(), QJSValue::PropertySetter);
2056         object.setProperty("foo", str);
2057
2058         // getter should still work
2059         QCOMPARE(object.property("foo").strictlyEquals(num), true);
2060
2061         // kill the getter too
2062         object.setProperty("foo", QJSValue(), QJSValue::PropertyGetter);
2063         // now foo is just a regular property
2064         object.setProperty("foo", str);
2065         QCOMPARE(object.property("x").strictlyEquals(num), true);
2066         QCOMPARE(object.property("foo").strictlyEquals(str), true);
2067     }
2068
2069     // use a single function as both getter and setter
2070     object.setProperty("foo", QJSValue());
2071     object.setProperty("foo", eng.newFunction(getterSetter),
2072                         QJSValue::PropertyGetter | QJSValue::PropertySetter);
2073     QCOMPARE(object.propertyFlags("foo"),
2074              QJSValue::PropertyGetter | QJSValue::PropertySetter);
2075     object.setProperty("x", num);
2076     QCOMPARE(object.property("foo").strictlyEquals(num), true);
2077
2078     // killing the getter will preserve the setter, even though they are the same function
2079     object.setProperty("foo", QJSValue(), QJSValue::PropertyGetter);
2080     QVERIFY(object.propertyFlags("foo") & QJSValue::PropertySetter);
2081     QCOMPARE(object.property("foo").isUndefined(), true);
2082 #endif
2083 }
2084
2085 void tst_QJSValue::getSetProperty_gettersAndSettersThrowErrorNative()
2086 {
2087 #if 0 // FIXME: No setters/getters right now
2088     // getter/setter that throws an error
2089     QScriptEngine eng;
2090     QJSValue str = QJSValue(&eng, "bar");
2091     QJSValue object = eng.newObject();
2092
2093     object.setProperty("foo", eng.newFunction(getterSetterThrowingError),
2094                         QJSValue::PropertyGetter | QJSValue::PropertySetter);
2095     QVERIFY(!eng.hasUncaughtException());
2096     QJSValue ret = object.property("foo");
2097     QVERIFY(ret.isError());
2098     QVERIFY(eng.hasUncaughtException());
2099     QVERIFY(ret.strictlyEquals(eng.uncaughtException()));
2100     QCOMPARE(ret.toString(), QLatin1String("Error: get foo"));
2101     eng.evaluate("Object"); // clear exception state...
2102     QVERIFY(!eng.hasUncaughtException());
2103     object.setProperty("foo", str);
2104     QVERIFY(eng.hasUncaughtException());
2105     QCOMPARE(eng.uncaughtException().toString(), QLatin1String("Error: set foo"));
2106 #endif
2107 }
2108
2109 void tst_QJSValue::getSetProperty_gettersAndSettersThrowErrorJS()
2110 {
2111     // getter/setter that throws an error (from js function)
2112     QJSEngine eng;
2113     QJSValue str = QJSValue(&eng, QLatin1String("bar"));
2114
2115     eng.evaluate("o = new Object; "
2116                  "o.__defineGetter__('foo', function() { throw new Error('get foo') }); "
2117                  "o.__defineSetter__('foo', function() { throw new Error('set foo') }); ");
2118     QJSValue object = eng.evaluate("o");
2119     QVERIFY(!eng.hasUncaughtException());
2120     QJSValue ret = object.property("foo");
2121     QVERIFY(ret.isError());
2122     QVERIFY(eng.hasUncaughtException());
2123     QVERIFY(ret.strictlyEquals(eng.uncaughtException()));
2124     QCOMPARE(ret.toString(), QLatin1String("Error: get foo"));
2125     eng.evaluate("Object"); // clear exception state...
2126     QVERIFY(!eng.hasUncaughtException());
2127     object.setProperty("foo", str);
2128     QVERIFY(eng.hasUncaughtException());
2129     QCOMPARE(eng.uncaughtException().toString(), QLatin1String("Error: set foo"));
2130 }
2131
2132 void tst_QJSValue::getSetProperty_gettersAndSettersOnNative()
2133 {
2134 #if 0 // FIXME: No c-style functions right now
2135     // attempt to install getter+setter on built-in (native) property
2136     QScriptEngine eng;
2137     QJSValue object = eng.newObject();
2138     QVERIFY(object.property("__proto__").strictlyEquals(object.prototype()));
2139
2140     QJSValue fun = eng.newFunction(getSet__proto__);
2141     fun.setProperty("value", QJSValue(&eng, "boo"));
2142 /*    QTest::ignoreMessage(QtWarningMsg, "QJSValue::setProperty() failed: "
2143                          "cannot set getter or setter of native property "
2144                          "`__proto__'");*/
2145     object.setProperty("__proto__", fun,
2146                         QJSValue::PropertyGetter | QJSValue::PropertySetter
2147                         | QJSValue::UserRange);
2148     QVERIFY(object.property("__proto__").strictlyEquals(object.prototype()));
2149
2150     object.setProperty("__proto__", QJSValue(),
2151                         QJSValue::PropertyGetter | QJSValue::PropertySetter);
2152     QVERIFY(object.property("__proto__").strictlyEquals(object.prototype()));
2153 #endif
2154 }
2155
2156 void tst_QJSValue::getSetProperty_gettersAndSettersOnGlobalObject()
2157 {
2158 #if 0 // FIXME: No c-style functions right now
2159     // global property that's a getter+setter
2160     QScriptEngine eng;
2161     eng.globalObject().setProperty("globalGetterSetterProperty", eng.newFunction(getterSetter),
2162                                    QJSValue::PropertyGetter | QJSValue::PropertySetter);
2163     eng.evaluate("globalGetterSetterProperty = 123");
2164     {
2165         QJSValue ret = eng.evaluate("globalGetterSetterProperty");
2166         QVERIFY(ret.isNumber());
2167         QVERIFY(ret.strictlyEquals(QJSValue(&eng, 123)));
2168     }
2169     QCOMPARE(eng.evaluate("typeof globalGetterSetterProperty").toString(),
2170              QString::fromLatin1("number"));
2171     {
2172         QJSValue ret = eng.evaluate("this.globalGetterSetterProperty()");
2173         QVERIFY(ret.isError());
2174         QCOMPARE(ret.toString(), QString::fromLatin1("TypeError: Property 'globalGetterSetterProperty' of object #<Object> is not a function"));
2175     }
2176     {
2177         QJSValue ret = eng.evaluate("new this.globalGetterSetterProperty()");
2178         QVERIFY(ret.isError());
2179         QCOMPARE(ret.toString(), QString::fromLatin1("TypeError: number is not a function"));
2180     }
2181 #endif
2182 }
2183
2184 void tst_QJSValue::getSetProperty_gettersAndSettersChange()
2185 {
2186 #if 0 // FIXME: No setters/getters API right now
2187     // "upgrading" an existing property to become a getter+setter
2188     QScriptEngine eng;
2189     QJSValue object = eng.newObject();
2190     QJSValue num(&eng, 123);
2191     object.setProperty("foo", num);
2192     object.setProperty("foo", eng.newFunction(getterSetter),
2193                         QJSValue::PropertyGetter | QJSValue::PropertySetter);
2194     QVERIFY(!object.property("x").isValid());
2195     object.setProperty("foo", num);
2196     QVERIFY(object.property("x").equals(num));
2197
2198     eng.globalObject().setProperty("object", object);
2199     QJSValue res = eng.evaluate("object.x = 89; var a = object.foo; object.foo = 65; a");
2200     QCOMPARE(res.toInt(), 89);
2201     QCOMPARE(object.property("x").toInt(), 65);
2202     QCOMPARE(object.property("foo").toInt(), 65);
2203 #endif
2204 }
2205
2206 void tst_QJSValue::getSetProperty_array()
2207 {
2208     QJSEngine eng;
2209     QJSValue str = QJSValue(&eng, QLatin1String("bar"));
2210     QJSValue num = QJSValue(&eng, 123.0);
2211     QJSValue array = eng.newArray();
2212
2213     QVERIFY(array.isArray());
2214     array.setProperty(0, num);
2215     QCOMPARE(array.property(0).toNumber(), num.toNumber());
2216     QCOMPARE(array.property("0").toNumber(), num.toNumber());
2217     QCOMPARE(array.property("length").toUInt(), quint32(1));
2218     array.setProperty(1, str);
2219     QCOMPARE(array.property(1).toString(), str.toString());
2220     QCOMPARE(array.property("1").toString(), str.toString());
2221     QCOMPARE(array.property("length").toUInt(), quint32(2));
2222     array.setProperty("length", QJSValue(&eng, 1));
2223     QCOMPARE(array.property("length").toUInt(), quint32(1));
2224     QCOMPARE(array.property(1).isValid(), false);
2225 }
2226
2227 void tst_QJSValue::getSetProperty_gettersAndSettersStupid()
2228 {
2229 #if 0 // FIXME: No setters/getters API right now
2230     //removing unexisting Setter or Getter should not crash.
2231     QScriptEngine eng;
2232     QJSValue num = QJSValue(&eng, 123.0);
2233
2234     {
2235         QJSValue object = eng.newObject();
2236         object.setProperty("foo", QJSValue(), QJSValue::PropertyGetter);
2237         QVERIFY(!object.property("foo").isValid());
2238         object.setProperty("foo", num);
2239         QCOMPARE(object.property("foo").strictlyEquals(num), true);
2240     }
2241
2242     {
2243         QJSValue object = eng.newObject();
2244         object.setProperty("foo", QJSValue(), QJSValue::PropertySetter);
2245         QVERIFY(!object.property("foo").isValid());
2246         object.setProperty("foo", num);
2247         QCOMPARE(object.property("foo").strictlyEquals(num), true);
2248     }
2249
2250     {
2251         QJSValue object = eng.globalObject();
2252         object.setProperty("foo", QJSValue(), QJSValue::PropertySetter);
2253         object.setProperty("foo", QJSValue(), QJSValue::PropertyGetter);
2254         QVERIFY(!object.property("foo").isValid());
2255         object.setProperty("foo", num);
2256         QCOMPARE(object.property("foo").strictlyEquals(num), true);
2257     }
2258 #endif
2259 }
2260
2261 void tst_QJSValue::getSetProperty()
2262 {
2263     QJSEngine eng;
2264
2265     QJSValue object = eng.newObject();
2266
2267     QJSValue str = QJSValue(&eng, QLatin1String("bar"));
2268     object.setProperty("foo", str);
2269     QCOMPARE(object.property("foo").toString(), str.toString());
2270
2271     QJSValue num = QJSValue(&eng, 123.0);
2272     object.setProperty("baz", num);
2273     QCOMPARE(object.property("baz").toNumber(), num.toNumber());
2274
2275     QJSValue strstr = QJSValue("bar");
2276     QCOMPARE(strstr.engine(), (QJSEngine *)0);
2277     object.setProperty("foo", strstr);
2278     QCOMPARE(object.property("foo").toString(), strstr.toString());
2279     QCOMPARE(strstr.engine(), &eng); // the value has been bound to the engine
2280
2281     QJSValue numnum = QJSValue(123.0);
2282     object.setProperty("baz", numnum);
2283     QCOMPARE(object.property("baz").toNumber(), numnum.toNumber());
2284
2285     QJSValue inv;
2286     inv.setProperty("foo", num);
2287     QCOMPARE(inv.property("foo").isValid(), false);
2288
2289     eng.globalObject().setProperty("object", object);
2290
2291 #if 0 // FIXME: no setProperty API with flags
2292   // ReadOnly
2293     object.setProperty("readOnlyProperty", num, QJSValue::ReadOnly);
2294     QCOMPARE(object.propertyFlags("readOnlyProperty"), QJSValue::ReadOnly);
2295     QCOMPARE(object.property("readOnlyProperty").strictlyEquals(num), true);
2296     eng.evaluate("object.readOnlyProperty = !object.readOnlyProperty");
2297     QCOMPARE(object.property("readOnlyProperty").strictlyEquals(num), true);
2298     // should still be part of enumeration
2299     {
2300         QJSValue ret = eng.evaluate(
2301             "found = false;"
2302             "for (var p in object) {"
2303             "  if (p == 'readOnlyProperty') {"
2304             "    found = true; break;"
2305             "  }"
2306             "} found");
2307         QCOMPARE(ret.strictlyEquals(QJSValue(&eng, true)), true);
2308     }
2309     // should still be deletable
2310     {
2311         QJSValue ret = eng.evaluate("delete object.readOnlyProperty");
2312         QCOMPARE(ret.strictlyEquals(QJSValue(&eng, true)), true);
2313         QCOMPARE(object.property("readOnlyProperty").isValid(), false);
2314     }
2315
2316   // Undeletable
2317     object.setProperty("undeletableProperty", num, QJSValue::Undeletable);
2318     QCOMPARE(object.propertyFlags("undeletableProperty"), QJSValue::Undeletable);
2319     QCOMPARE(object.property("undeletableProperty").strictlyEquals(num), true);
2320     {
2321         QJSValue ret = eng.evaluate("delete object.undeletableProperty");
2322         QCOMPARE(ret.strictlyEquals(QJSValue(&eng, true)), false);
2323         QCOMPARE(object.property("undeletableProperty").strictlyEquals(num), true);
2324     }
2325     // should still be writable
2326     eng.evaluate("object.undeletableProperty = object.undeletableProperty + 1");
2327     QCOMPARE(object.property("undeletableProperty").toNumber(), num.toNumber() + 1);
2328     // should still be part of enumeration
2329     {
2330         QJSValue ret = eng.evaluate(
2331             "found = false;"
2332             "for (var p in object) {"
2333             "  if (p == 'undeletableProperty') {"
2334             "    found = true; break;"
2335             "  }"
2336             "} found");
2337         QCOMPARE(ret.strictlyEquals(QJSValue(&eng, true)), true);
2338     }
2339     // should still be deletable from C++
2340     object.setProperty("undeletableProperty", QJSValue());
2341     QEXPECT_FAIL("", "QTBUG-17617: With JSC-based back-end, undeletable properties can't be deleted from C++", Continue);
2342     QVERIFY(!object.property("undeletableProperty").isValid());
2343     QEXPECT_FAIL("", "QTBUG-17617: With JSC-based back-end, undeletable properties can't be deleted from C++", Continue);
2344     QCOMPARE(object.propertyFlags("undeletableProperty"), 0);
2345
2346   // SkipInEnumeration
2347     object.setProperty("dontEnumProperty", num, QJSValue::SkipInEnumeration);
2348     QCOMPARE(object.propertyFlags("dontEnumProperty"), QJSValue::SkipInEnumeration);
2349     QCOMPARE(object.property("dontEnumProperty").strictlyEquals(num), true);
2350     // should not be part of enumeration
2351     {
2352         QJSValue ret = eng.evaluate(
2353             "found = false;"
2354             "for (var p in object) {"
2355             "  if (p == 'dontEnumProperty') {"
2356             "    found = true; break;"
2357             "  }"
2358             "} found");
2359         QCOMPARE(ret.strictlyEquals(QJSValue(&eng, false)), true);
2360     }
2361     // should still be writable
2362     eng.evaluate("object.dontEnumProperty = object.dontEnumProperty + 1");
2363     QCOMPARE(object.property("dontEnumProperty").toNumber(), num.toNumber() + 1);
2364     // should still be deletable
2365     {
2366         QJSValue ret = eng.evaluate("delete object.dontEnumProperty");
2367         QCOMPARE(ret.strictlyEquals(QJSValue(&eng, true)), true);
2368         QCOMPARE(object.property("dontEnumProperty").isValid(), false);
2369     }
2370
2371     // change flags
2372     object.setProperty("flagProperty", str);
2373     QCOMPARE(object.propertyFlags("flagProperty"), static_cast<QJSValue::PropertyFlags>(0));
2374
2375     QEXPECT_FAIL("", "FIXME: v8 does not support changing flags of existing properties", Continue);
2376     //v8::i::JSObject::SetProperty(LookupResult* result, ... ) does not take in account the attributes
2377     // if the result->isFound()
2378     object.setProperty("flagProperty", str, QJSValue::ReadOnly);
2379     QCOMPARE(object.propertyFlags("flagProperty"), QJSValue::ReadOnly);
2380
2381     QEXPECT_FAIL("", "FIXME: v8 does not support changing flags of existing properties", Continue);
2382     object.setProperty("flagProperty", str, object.propertyFlags("flagProperty") | QJSValue::SkipInEnumeration);
2383     QCOMPARE(object.propertyFlags("flagProperty"), QJSValue::ReadOnly | QJSValue::SkipInEnumeration);
2384
2385     QEXPECT_FAIL("", "FIXME: v8 does not support changing flags of existing properties", Continue);
2386     object.setProperty("flagProperty", str, QJSValue::KeepExistingFlags);
2387     QCOMPARE(object.propertyFlags("flagProperty"), QJSValue::ReadOnly | QJSValue::SkipInEnumeration);
2388
2389     QEXPECT_FAIL("", "FIXME: v8 does not support UserRange", Continue);
2390     object.setProperty("flagProperty", str, QJSValue::UserRange);
2391     QCOMPARE(object.propertyFlags("flagProperty"), QJSValue::UserRange);
2392
2393     // flags of property in the prototype
2394     {
2395         QJSValue object2 = eng.newObject();
2396         object2.setPrototype(object);
2397         QCOMPARE(object2.propertyFlags("flagProperty", QJSValue::ResolveLocal), 0);
2398         QEXPECT_FAIL("", "FIXME: v8 does not support UserRange", Continue);
2399         QCOMPARE(object2.propertyFlags("flagProperty"), QJSValue::UserRange);
2400     }
2401
2402     // using interned strings
2403     QScriptString foo = eng.toStringHandle("foo");
2404
2405     object.setProperty(foo, QJSValue());
2406     QVERIFY(!object.property(foo).isValid());
2407
2408     object.setProperty(foo, num);
2409     QVERIFY(object.property(foo).strictlyEquals(num));
2410     QVERIFY(object.property("foo").strictlyEquals(num));
2411     QVERIFY(object.propertyFlags(foo) == 0);
2412 #endif
2413
2414     // Setting index property on non-Array
2415     object.setProperty(13, num);
2416     QVERIFY(object.property(13).equals(num));
2417 }
2418
2419 void tst_QJSValue::arrayElementGetterSetter()
2420 {
2421 #if 0 // FIXME: No c-style functions
2422     QScriptEngine eng;
2423     QJSValue obj = eng.newObject();
2424     obj.setProperty(1, eng.newFunction(getterSetter), QJSValue::PropertyGetter|QJSValue::PropertySetter);
2425     {
2426         QJSValue num(123);
2427         obj.setProperty("x", num);
2428         QJSValue ret = obj.property(1);
2429         QVERIFY(ret.isValid());
2430         QVERIFY(ret.equals(num));
2431     }
2432     {
2433         QJSValue num(456);
2434         obj.setProperty(1, num);
2435         QJSValue ret = obj.property(1);
2436         QVERIFY(ret.isValid());
2437         QVERIFY(ret.equals(num));
2438         QVERIFY(ret.equals(obj.property("1")));
2439     }
2440     QCOMPARE(obj.propertyFlags("1"), QJSValue::PropertyGetter|QJSValue::PropertySetter);
2441
2442     obj.setProperty(1, QJSValue(), QJSValue::PropertyGetter|QJSValue::PropertySetter);
2443     QVERIFY(obj.propertyFlags("1") == 0);
2444 #endif
2445 }
2446
2447 void tst_QJSValue::getSetPrototype_cyclicPrototype()
2448 {
2449     QJSEngine eng;
2450     QJSValue prototype = eng.newObject();
2451     QJSValue object = eng.newObject();
2452     object.setPrototype(prototype);
2453
2454     QJSValue previousPrototype = prototype.prototype();
2455     QTest::ignoreMessage(QtWarningMsg, "QJSValue::setPrototype() failed: cyclic prototype value");
2456     prototype.setPrototype(prototype);
2457     QCOMPARE(prototype.prototype().strictlyEquals(previousPrototype), true);
2458
2459     object.setPrototype(prototype);
2460     QTest::ignoreMessage(QtWarningMsg, "QJSValue::setPrototype() failed: cyclic prototype value");
2461     prototype.setPrototype(object);
2462     QCOMPARE(prototype.prototype().strictlyEquals(previousPrototype), true);
2463
2464 }
2465
2466 void tst_QJSValue::getSetPrototype_evalCyclicPrototype()
2467 {
2468     QJSEngine eng;
2469     QJSValue ret = eng.evaluate("o = { }; p = { }; o.__proto__ = p; p.__proto__ = o");
2470     QCOMPARE(eng.hasUncaughtException(), true);
2471     QVERIFY(ret.strictlyEquals(eng.uncaughtException()));
2472     QCOMPARE(ret.isError(), true);
2473     QCOMPARE(ret.toString(), QLatin1String("Error: Cyclic __proto__ value"));
2474 }
2475
2476 void tst_QJSValue::getSetPrototype_eval()
2477 {
2478     QJSEngine eng;
2479     QJSValue ret = eng.evaluate("p = { }; p.__proto__ = { }");
2480     QCOMPARE(eng.hasUncaughtException(), false);
2481     QCOMPARE(ret.isError(), false);
2482 }
2483
2484 void tst_QJSValue::getSetPrototype_invalidPrototype()
2485 {
2486     QJSEngine eng;
2487     QJSValue inv;
2488     QJSValue object = eng.newObject();
2489     QJSValue proto = object.prototype();
2490     QVERIFY(object.prototype().strictlyEquals(proto));
2491     inv.setPrototype(object);
2492     QCOMPARE(inv.prototype().isValid(), false);
2493     object.setPrototype(inv);
2494     QVERIFY(object.prototype().strictlyEquals(proto));
2495 }
2496
2497 void tst_QJSValue::getSetPrototype_twoEngines()
2498 {
2499     QJSEngine eng;
2500     QJSValue prototype = eng.newObject();
2501     QJSValue object = eng.newObject();
2502     object.setPrototype(prototype);
2503     QJSEngine otherEngine;
2504     QJSValue newPrototype = otherEngine.newObject();
2505     QTest::ignoreMessage(QtWarningMsg, "QJSValue::setPrototype() failed: cannot set a prototype created in a different engine");
2506     object.setPrototype(newPrototype);
2507     QCOMPARE(object.prototype().strictlyEquals(prototype), true);
2508
2509 }
2510
2511 void tst_QJSValue::getSetPrototype_null()
2512 {
2513     QJSEngine eng;
2514     QJSValue object = eng.newObject();
2515     object.setPrototype(QJSValue(QJSValue::NullValue));
2516     QVERIFY(object.prototype().isNull());
2517
2518     QJSValue newProto = eng.newObject();
2519     object.setPrototype(newProto);
2520     QVERIFY(object.prototype().equals(newProto));
2521
2522     object.setPrototype(QJSValue(&eng, QJSValue::NullValue));
2523     QVERIFY(object.prototype().isNull());
2524 }
2525
2526 void tst_QJSValue::getSetPrototype_notObjectOrNull()
2527 {
2528     QJSEngine eng;
2529     QJSValue object = eng.newObject();
2530     QJSValue originalProto = object.prototype();
2531
2532     // bool
2533     object.setPrototype(true);
2534     QVERIFY(object.prototype().equals(originalProto));
2535     object.setPrototype(QJSValue(&eng, true));
2536     QVERIFY(object.prototype().equals(originalProto));
2537
2538     // number
2539     object.setPrototype(123);
2540     QVERIFY(object.prototype().equals(originalProto));
2541     object.setPrototype(QJSValue(&eng, 123));
2542     QVERIFY(object.prototype().equals(originalProto));
2543
2544     // string
2545     object.setPrototype("foo");
2546     QVERIFY(object.prototype().equals(originalProto));
2547     object.setPrototype(QJSValue(&eng, QLatin1String("foo")));
2548     QVERIFY(object.prototype().equals(originalProto));
2549
2550     // undefined
2551     object.setPrototype(QJSValue(QJSValue::UndefinedValue));
2552     QVERIFY(object.prototype().equals(originalProto));
2553     object.setPrototype(QJSValue(&eng, QJSValue::UndefinedValue));
2554     QVERIFY(object.prototype().equals(originalProto));
2555 }
2556
2557 void tst_QJSValue::getSetPrototype()
2558 {
2559     QJSEngine eng;
2560     QJSValue prototype = eng.newObject();
2561     QJSValue object = eng.newObject();
2562     object.setPrototype(prototype);
2563     QCOMPARE(object.prototype().strictlyEquals(prototype), true);
2564 }
2565
2566 void tst_QJSValue::getSetScope()
2567 {
2568 #if 0 // FIXME: No QJSValue::scope
2569     QScriptEngine eng;
2570
2571     QJSValue object = eng.newObject();
2572     QCOMPARE(object.scope().isValid(), false);
2573
2574     QJSValue object2 = eng.newObject();
2575     object2.setScope(object);
2576
2577     QEXPECT_FAIL("", "FIXME: scope not implemented yet", Abort);
2578     QCOMPARE(object2.scope().strictlyEquals(object), true);
2579
2580     object.setProperty("foo", 123);
2581     QVERIFY(!object2.property("foo").isValid());
2582     {
2583         QJSValue ret = object2.property("foo", QJSValue::ResolveScope);
2584         QVERIFY(ret.isNumber());
2585         QCOMPARE(ret.toInt(), 123);
2586     }
2587
2588     QJSValue inv;
2589     inv.setScope(object);
2590     QCOMPARE(inv.scope().isValid(), false);
2591
2592     QScriptEngine otherEngine;
2593     QJSValue object3 = otherEngine.newObject();
2594     QTest::ignoreMessage(QtWarningMsg, "QJSValue::setScope() failed: cannot set a scope object created in a different engine");
2595     object2.setScope(object3);
2596     QCOMPARE(object2.scope().strictlyEquals(object), true);
2597
2598     object2.setScope(QJSValue());
2599     QVERIFY(!object2.scope().isValid());
2600 #endif
2601 }
2602
2603 void tst_QJSValue::getSetData_objects_data()
2604 {
2605 #if 0 // FIXME: no setData/data API
2606     newEngine();
2607
2608     QTest::addColumn<QJSValue>("object");
2609
2610     QTest::newRow("object from evaluate") << engine->evaluate("new Object()");
2611     QTest::newRow("object from engine") << engine->newObject();
2612     QTest::newRow("Array") << engine->newArray();
2613     QTest::newRow("Date") << engine->newDate(12324);
2614     QTest::newRow("QObject") << engine->newQObject(this);
2615     QTest::newRow("RegExp") << engine->newRegExp(QRegExp());
2616 #endif
2617 }
2618
2619 void tst_QJSValue::getSetData_objects()
2620 {
2621 #if 0 // FIXME: no setData/data API
2622     QFETCH(QJSValue, object);
2623
2624     QVERIFY(!object.data().isValid());
2625     QJSValue v1(true);
2626     object.setData(v1);
2627     QVERIFY(object.data().strictlyEquals(v1));
2628     QJSValue v2(123);
2629     object.setData(v2);
2630     QVERIFY(object.data().strictlyEquals(v2));
2631     QJSValue v3 = engine->newObject();
2632     object.setData(v3);
2633     QVERIFY(object.data().strictlyEquals(v3));
2634     object.setData(QJSValue());
2635     QVERIFY(!object.data().isValid());
2636 #endif
2637 }
2638
2639 void tst_QJSValue::getSetData_nonObjects_data()
2640 {
2641 #if 0 // FIXME: no setData/data API
2642     newEngine();
2643
2644     QTest::addColumn<QJSValue>("value");
2645
2646     QTest::newRow("undefined (bound)") << engine->undefinedValue();
2647     QTest::newRow("null (bound)") << engine->nullValue();
2648     QTest::newRow("string (bound)") << QJSValue(engine, "Pong");
2649     QTest::newRow("bool (bound)") << QJSValue(engine, false);
2650
2651     QTest::newRow("undefined") << QJSValue(QJSValue::UndefinedValue);
2652     QTest::newRow("null") << QJSValue(QJSValue::NullValue);
2653     QTest::newRow("string") << QJSValue("Pong");
2654     QTest::newRow("bool") << QJSValue(true);
2655 #endif
2656 }
2657
2658 void tst_QJSValue::getSetData_nonObjects()
2659 {
2660 #if 0 // FIXME: no setData/data API
2661     QFETCH(QJSValue, value);
2662
2663     QVERIFY(!value.data().isValid());
2664     QJSValue v1(true);
2665     value.setData(v1);
2666     QVERIFY(!value.data().isValid());
2667     QJSValue v2(123);
2668     value.setData(v2);
2669     QVERIFY(!value.data().isValid());
2670     QJSValue v3 = engine->newObject();
2671     value.setData(v3);
2672     QVERIFY(!value.data().isValid());
2673     value.setData(QJSValue());
2674     QVERIFY(!value.data().isValid());
2675 #endif
2676 }
2677
2678 void tst_QJSValue::setData_QTBUG15144()
2679 {
2680 #if 0 // FIXME: no setData/data API
2681     QScriptEngine eng;
2682     QJSValue obj = eng.newObject();
2683     for (int i = 0; i < 10000; ++i) {
2684         // Create an object with property 'fooN' on it, and immediately kill
2685         // the reference to the object so it and the property name become garbage.
2686         eng.evaluate(QString::fromLatin1("o = {}; o.foo%0 = 10; o = null;").arg(i));
2687         // Setting the data will cause a JS string to be allocated, which could
2688         // trigger a GC. This should not cause a crash.
2689         obj.setData("foodfight");
2690     }
2691 #endif
2692 }
2693
2694 #if 0 // FIXME: no QScriptClass
2695 class TestScriptClass : public QScriptClass
2696 {
2697 public:
2698     TestScriptClass(QScriptEngine *engine) : QScriptClass(engine) {}
2699 };
2700
2701 void tst_QJSValue::getSetScriptClass_emptyClass_data()
2702 {
2703     newEngine();
2704     QTest::addColumn<QJSValue>("value");
2705
2706     QTest::newRow("invalid") << QJSValue();
2707     QTest::newRow("number") << QJSValue(123);
2708     QTest::newRow("string") << QJSValue("pong");
2709     QTest::newRow("bool") << QJSValue(false);
2710     QTest::newRow("null") << QJSValue(QJSValue::NullValue);
2711     QTest::newRow("undefined") << QJSValue(QJSValue::UndefinedValue);
2712
2713     QTest::newRow("number") << QJSValue(engine, 123);
2714     QTest::newRow("string") << QJSValue(engine, "pong");
2715     QTest::newRow("bool") << QJSValue(engine, true);
2716     QTest::newRow("null") << QJSValue(engine->nullValue());
2717     QTest::newRow("undefined") << QJSValue(engine->undefinedValue());
2718     QTest::newRow("object") << QJSValue(engine->newObject());
2719     QTest::newRow("date") << QJSValue(engine->evaluate("new Date()"));
2720     QTest::newRow("qobject") << QJSValue(engine->newQObject(this));
2721 }
2722
2723 void tst_QJSValue::getSetScriptClass_emptyClass()
2724 {
2725     QFETCH(QJSValue, value);
2726     QCOMPARE(value.scriptClass(), (QScriptClass*)0);
2727 }
2728
2729 void tst_QJSValue::getSetScriptClass_JSObjectFromCpp()
2730 {
2731     QScriptEngine eng;
2732     TestScriptClass testClass(&eng);
2733     // object created in C++ (newObject())
2734     {
2735         QJSValue obj = eng.newObject();
2736         obj.setScriptClass(&testClass);
2737         QCOMPARE(obj.scriptClass(), (QScriptClass*)&testClass);
2738         obj.setScriptClass(0);
2739         QCOMPARE(obj.scriptClass(), (QScriptClass*)0);
2740     }
2741 }
2742
2743 void tst_QJSValue::getSetScriptClass_JSObjectFromJS()
2744 {
2745     QScriptEngine eng;
2746     TestScriptClass testClass(&eng);
2747     // object created in JS
2748     {
2749         QJSValue obj = eng.evaluate("new Object");
2750         QVERIFY(!eng.hasUncaughtException());
2751         QVERIFY(obj.isObject());
2752         QCOMPARE(obj.scriptClass(), (QScriptClass*)0);
2753         obj.setScriptClass(&testClass);
2754         QCOMPARE(obj.scriptClass(), (QScriptClass*)&testClass);
2755         obj.setScriptClass(0);
2756         QCOMPARE(obj.scriptClass(), (QScriptClass*)0);
2757     }
2758 }
2759
2760 void tst_QJSValue::getSetScriptClass_QVariant()
2761 {
2762     QScriptEngine eng;
2763     TestScriptClass testClass(&eng);
2764     // object that already has a(n internal) class
2765     {
2766         QJSValue obj = eng.newVariant(QUrl("http://example.com"));
2767         QVERIFY(obj.isVariant());
2768         QCOMPARE(obj.scriptClass(), (QScriptClass*)0);
2769         obj.setScriptClass(&testClass);
2770         QCOMPARE(obj.scriptClass(), (QScriptClass*)&testClass);
2771         QVERIFY(obj.isObject());
2772         QVERIFY(!obj.isVariant());
2773         QCOMPARE(obj.toVariant(), QVariant(QVariantMap()));
2774     }
2775 }
2776
2777 void tst_QJSValue::getSetScriptClass_QObject()
2778 {
2779     QScriptEngine eng;
2780     TestScriptClass testClass(&eng);
2781     {
2782         QJSValue obj = eng.newQObject(this);
2783         QVERIFY(obj.isQObject());
2784         obj.setScriptClass(&testClass);
2785         QCOMPARE(obj.scriptClass(), (QScriptClass*)&testClass);
2786         QVERIFY(obj.isObject());
2787         QVERIFY(!obj.isQObject());
2788         QVERIFY(obj.toQObject() == 0);
2789     }
2790 }
2791 #endif
2792
2793 #if 0 // FIXME: No c-style callbacks
2794 static QJSValue getArg(QScriptContext *ctx, QScriptEngine *)
2795 {
2796     return ctx->argument(0);
2797 }
2798
2799 static QJSValue evaluateArg(QScriptContext *, QScriptEngine *eng)
2800 {
2801     return eng->evaluate("arguments[0]");
2802 }
2803
2804 static QJSValue addArgs(QScriptContext *, QScriptEngine *eng)
2805 {
2806     return eng->evaluate("arguments[0] + arguments[1]");
2807 }
2808
2809 static QJSValue returnInvalidValue(QScriptContext *, QScriptEngine *)
2810 {
2811     return QJSValue();
2812 }
2813 #endif
2814
2815 void tst_QJSValue::call_function()
2816 {
2817     QJSEngine eng;
2818     QJSValue fun = eng.evaluate("(function() { return 1; })");
2819     QVERIFY(fun.isCallable());
2820     QJSValue result = fun.call();
2821     QVERIFY(result.isNumber());
2822     QCOMPARE(result.toInt(), 1);
2823 }
2824
2825 void tst_QJSValue::call_object()
2826 {
2827     QJSEngine eng;
2828     QJSValue Object = eng.evaluate("Object");
2829     QCOMPARE(Object.isCallable(), true);
2830     QJSValue result = Object.callWithInstance(Object);
2831     QCOMPARE(result.isObject(), true);
2832 }
2833
2834 void tst_QJSValue::call_newObjects()
2835 {
2836     QJSEngine eng;
2837     // test that call() doesn't construct new objects
2838     QJSValue Number = eng.evaluate("Number");
2839     QJSValue Object = eng.evaluate("Object");
2840     QCOMPARE(Object.isCallable(), true);
2841     QJSValueList args;
2842     args << QJSValue(&eng, 123);
2843     QJSValue result = Number.callWithInstance(Object, args);
2844     QCOMPARE(result.strictlyEquals(args.at(0)), true);
2845 }
2846
2847 void tst_QJSValue::call_this()
2848 {
2849     QJSEngine eng;
2850     // test that correct "this" object is used
2851     QJSValue fun = eng.evaluate("(function() { return this; })");
2852     QCOMPARE(fun.isCallable(), true);
2853
2854     QJSValue numberObject = QJSValue(&eng, 123.0).toObject();
2855     QJSValue result = fun.callWithInstance(numberObject);
2856     QCOMPARE(result.isObject(), true);
2857     QCOMPARE(result.toNumber(), 123.0);
2858 }
2859
2860 void tst_QJSValue::call_arguments()
2861 {
2862     QJSEngine eng;
2863     // test that correct arguments are passed
2864
2865     QJSValue fun = eng.evaluate("(function() { return arguments[0]; })");
2866     QCOMPARE(fun.isCallable(), true);
2867     {
2868         QJSValue result = fun.callWithInstance(eng.undefinedValue());
2869         QCOMPARE(result.isUndefined(), true);
2870     }
2871     {
2872         QJSValueList args;
2873         args << QJSValue(&eng, 123.0);
2874         QJSValue result = fun.callWithInstance(eng.undefinedValue(), args);
2875         QCOMPARE(result.isNumber(), true);
2876         QCOMPARE(result.toNumber(), 123.0);
2877     }
2878     // V2 constructors
2879     {
2880         QJSValueList args;
2881         args << QJSValue(123.0);
2882         QJSValue result = fun.callWithInstance(eng.undefinedValue(), args);
2883         QCOMPARE(result.isNumber(), true);
2884         QCOMPARE(result.toNumber(), 123.0);
2885     }
2886 #if 0 // FIXME: The feature of interpreting a passed array as argument list has been removed from the API
2887     {
2888         QJSValue args = eng.newArray();
2889         args.setProperty(0, 123);
2890         QJSValue result = fun.callWithInstance(eng.undefinedValue(), args);
2891         QVERIFY(result.isNumber());
2892         QCOMPARE(result.toNumber(), 123.0);
2893     }
2894 #endif
2895 }
2896
2897 void tst_QJSValue::call()
2898 {
2899     QJSEngine eng;
2900     {
2901         QJSValue fun = eng.evaluate("(function() { return arguments[1]; })");
2902         QCOMPARE(fun.isCallable(), true);
2903
2904         {
2905             QJSValueList args;
2906             args << QJSValue(&eng, 123.0) << QJSValue(&eng, 456.0);
2907             QJSValue result = fun.callWithInstance(eng.undefinedValue(), args);
2908             QCOMPARE(result.isNumber(), true);
2909             QCOMPARE(result.toNumber(), 456.0);
2910         }
2911 #if 0 // FIXME: The feature of interpreting a passed array as argument list has been removed from the API
2912         {
2913             QJSValue args = eng.newArray();
2914             args.setProperty(0, 123);
2915             args.setProperty(1, 456);
2916             QJSValue result = fun.callWithInstance(eng.undefinedValue(), args);
2917             QVERIFY(result.isNumber());
2918             QCOMPARE(result.toNumber(), 456.0);
2919         }
2920 #endif
2921     }
2922     {
2923         QJSValue fun = eng.evaluate("(function() { throw new Error('foo'); })");
2924         QCOMPARE(fun.isCallable(), true);
2925         QVERIFY(!eng.hasUncaughtException());
2926
2927         {
2928             QJSValue result = fun.call();
2929             QCOMPARE(result.isError(), true);
2930             QCOMPARE(eng.hasUncaughtException(), true);
2931             QVERIFY(result.strictlyEquals(eng.uncaughtException()));
2932         }
2933     }
2934 #if 0 // FIXME: No c-style callbacks
2935     {
2936         eng.clearExceptions();
2937         QJSValue fun = eng.newFunction(getArg);
2938         {
2939             QJSValueList args;
2940             args << QJSValue(&eng, 123.0);
2941             QJSValue result = fun.callWithInstance(eng.undefinedValue(), args);
2942             QVERIFY(!eng.hasUncaughtException());
2943             QCOMPARE(result.isNumber(), true);
2944             QCOMPARE(result.toNumber(), 123.0);
2945         }
2946         // V2 constructors
2947         {
2948             QJSValueList args;
2949             args << QJSValue(123.0);
2950             QJSValue result = fun.callWithInstance(eng.undefinedValue(), args);
2951             QCOMPARE(result.isNumber(), true);
2952             QCOMPARE(result.toNumber(), 123.0);
2953         }
2954 #if 0 // FIXME: The feature of interpreting a passed array as argument list has been removed from the API
2955         {
2956             QJSValue args = eng.newArray();
2957             args.setProperty(0, 123);
2958             QJSValue result = fun.callWithInstance(eng.undefinedValue(), args);
2959             QVERIFY(result.isNumber());
2960             QCOMPARE(result.toNumber(), 123.0);
2961         }
2962 #endif
2963     }
2964     {
2965         QJSValue fun = eng.newFunction(evaluateArg);
2966         {
2967             QJSValueList args;
2968             args << QJSValue(&eng, 123.0);
2969             QJSValue result = fun.callWithInstance(eng.undefinedValue(), args);
2970             QVERIFY(!eng.hasUncaughtException());
2971             QCOMPARE(result.isNumber(), true);
2972             QCOMPARE(result.toNumber(), 123.0);
2973         }
2974     }
2975 #endif
2976 }
2977
2978 void tst_QJSValue::call_invalidArguments()
2979 {
2980 #if 0 // FIXME: No c-style callbacks
2981     // test that invalid arguments are handled gracefully
2982     QScriptEngine eng;
2983     {
2984         QJSValue fun = eng.newFunction(getArg);
2985         {
2986             QJSValueList args;
2987             args << QJSValue();
2988             QJSValue ret = fun.callWithInstance(args);
2989             QVERIFY(!eng.hasUncaughtException());
2990             QCOMPARE(ret.isValid(), true);
2991             QCOMPARE(ret.isUndefined(), true);
2992         }
2993     }
2994     {
2995         QJSValue fun = eng.newFunction(evaluateArg);
2996         {
2997             QJSValueList args;
2998             args << QJSValue();
2999             QJSValue ret = fun.call(args);
3000             QCOMPARE(ret.isValid(), true);
3001             QCOMPARE(ret.isUndefined(), true);
3002         }
3003     }
3004     {
3005         QJSValue fun = eng.newFunction(addArgs);
3006         {
3007             QJSValueList args;
3008             args << QJSValue() << QJSValue();
3009             QJSValue ret = fun.call(args);
3010             QCOMPARE(ret.isValid(), true);
3011             QCOMPARE(ret.isNumber(), true);
3012             QCOMPARE(qIsNaN(ret.toNumber()), true);
3013         }
3014     }
3015 #endif
3016 }
3017
3018 void tst_QJSValue::call_invalidReturn()
3019 {
3020 #if 0 // FIXME: No c-style callbacks
3021     // test that invalid return value is handled gracefully
3022     QScriptEngine eng;
3023     QJSValue fun = eng.newFunction(returnInvalidValue);
3024     eng.globalObject().setProperty("returnInvalidValue", fun);
3025     QJSValue ret = eng.evaluate("returnInvalidValue() + returnInvalidValue()");
3026     QCOMPARE(ret.isValid(), true);
3027     QCOMPARE(ret.isNumber(), true);
3028     QCOMPARE(qIsNaN(ret.toNumber()), true);
3029 #endif
3030 }
3031
3032 void tst_QJSValue::call_twoEngines()
3033 {
3034     QJSEngine eng;
3035     QJSValue object = eng.evaluate("Object");
3036     QJSEngine otherEngine;
3037     QJSValue fun = otherEngine.evaluate("(function() { return 1; })");
3038     QVERIFY(fun.isCallable());
3039     QTest::ignoreMessage(QtWarningMsg, "JSValue can't be rassigned to an another engine.");
3040     QTest::ignoreMessage(QtWarningMsg, "QJSValue::call() failed: "
3041                          "cannot call function with thisObject created in "
3042                          "a different engine");
3043     QCOMPARE(fun.callWithInstance(object).isValid(), false);
3044     QTest::ignoreMessage(QtWarningMsg, "QJSValue::call() failed: "
3045                          "cannot call function with argument created in "
3046                          "a different engine");
3047     QCOMPARE(fun.call(QJSValueList() << QJSValue(&eng, 123)).isValid(), false);
3048     {
3049         QJSValue fun = eng.evaluate("Object");
3050         QVERIFY(fun.isCallable());
3051         QJSEngine eng2;
3052         QJSValue objectInDifferentEngine = eng2.newObject();
3053         QJSValueList args;
3054         args << objectInDifferentEngine;
3055         QTest::ignoreMessage(QtWarningMsg, "QJSValue::call() failed: cannot call function with argument created in a different engine");
3056         fun.call(args);
3057     }
3058 }
3059
3060 void tst_QJSValue::call_array()
3061 {
3062 #if 0 // FIXME: The feature of interpreting an array as argument list has been removed from the API
3063     QScriptEngine eng;
3064     QJSValue fun = eng.evaluate("(function() { return arguments; })");
3065     QVERIFY(fun.isCallable());
3066     QJSValue array = eng.newArray(3);
3067     array.setProperty(0, QJSValue(&eng, 123.0));
3068     array.setProperty(1, QJSValue(&eng, 456.0));
3069     array.setProperty(2, QJSValue(&eng, 789.0));
3070     // call with single array object as arguments
3071     QJSValue ret = fun.call(QJSValue(), array);
3072     QVERIFY(!eng.hasUncaughtException());
3073     QCOMPARE(ret.isError(), false);
3074     QCOMPARE(ret.property(0).strictlyEquals(array.property(0)), true);
3075     QCOMPARE(ret.property(1).strictlyEquals(array.property(1)), true);
3076     QCOMPARE(ret.property(2).strictlyEquals(array.property(2)), true);
3077     // call with arguments object as arguments
3078     QJSValue ret2 = fun.call(QJSValue(), ret);
3079     QCOMPARE(ret2.isError(), false);
3080     QCOMPARE(ret2.property(0).strictlyEquals(ret.property(0)), true);
3081     QCOMPARE(ret2.property(1).strictlyEquals(ret.property(1)), true);
3082     QCOMPARE(ret2.property(2).strictlyEquals(ret.property(2)), true);
3083     // call with null as arguments
3084     QJSValue ret3 = fun.call(QJSValue(), eng.nullValue());
3085     QCOMPARE(ret3.isError(), false);
3086     QCOMPARE(ret3.property("length").isNumber(), true);
3087     QCOMPARE(ret3.property("length").toNumber(), 0.0);
3088     // call with undefined as arguments
3089     QJSValue ret4 = fun.call(QJSValue(), eng.undefinedValue());
3090     QCOMPARE(ret4.isError(), false);
3091     QCOMPARE(ret4.property("length").isNumber(), true);
3092     QCOMPARE(ret4.property("length").toNumber(), 0.0);
3093     // call with something else as arguments
3094     QJSValue ret5 = fun.call(QJSValue(), QJSValue(&eng, 123.0));
3095     QCOMPARE(ret5.isError(), true);
3096     // call with a non-array object as arguments
3097     QJSValue ret6 = fun.call(QJSValue(), eng.globalObject());
3098     QVERIFY(ret6.isError());
3099     QCOMPARE(ret6.toString(), QString::fromLatin1("TypeError: Arguments must be an array"));
3100 #endif
3101 }
3102
3103
3104 void tst_QJSValue::call_nonFunction_data()
3105 {
3106     newEngine();
3107     QTest::addColumn<QJSValue>("value");
3108
3109     QTest::newRow("invalid") << QJSValue();
3110     QTest::newRow("bool") << QJSValue(false);
3111     QTest::newRow("int") << QJSValue(123);
3112     QTest::newRow("string") << QJSValue(QString::fromLatin1("ciao"));
3113     QTest::newRow("undefined") << QJSValue(QJSValue::UndefinedValue);
3114     QTest::newRow("null") << QJSValue(QJSValue::NullValue);
3115
3116     QTest::newRow("bool bound") << QJSValue(engine, false);
3117     QTest::newRow("int bound") << QJSValue(engine, 123);
3118     QTest::newRow("string bound") << QJSValue(engine, QString::fromLatin1("ciao"));
3119     QTest::newRow("undefined bound") << engine->undefinedValue();
3120     QTest::newRow("null bound") << engine->nullValue();
3121 }
3122
3123 void tst_QJSValue::call_nonFunction()
3124 {
3125     // calling things that are not functions
3126     QFETCH(QJSValue, value);
3127     QVERIFY(!value.call().isValid());
3128 }
3129
3130 #if 0 // FIXME: no c-style callbacks
3131 static QJSValue ctorReturningUndefined(QScriptContext *ctx, QScriptEngine *)
3132 {
3133     ctx->thisObject().setProperty("foo", 123);
3134     return QJSValue(QJSValue::UndefinedValue);
3135 }
3136
3137 static QJSValue ctorReturningNewObject(QScriptContext *, QScriptEngine *eng)
3138 {
3139     QJSValue result = eng->newObject();
3140     result.setProperty("bar", 456);
3141     return result;
3142 }
3143 #endif
3144
3145 void tst_QJSValue::construct_nonFunction_data()
3146 {
3147     newEngine();
3148     QTest::addColumn<QJSValue>("value");
3149
3150     QTest::newRow("invalid") << QJSValue();
3151     QTest::newRow("bool") << QJSValue(false);
3152     QTest::newRow("int") << QJSValue(123);
3153     QTest::newRow("string") << QJSValue(QString::fromLatin1("ciao"));
3154     QTest::newRow("undefined") << QJSValue(QJSValue::UndefinedValue);
3155     QTest::newRow("null") << QJSValue(QJSValue::NullValue);
3156
3157     QTest::newRow("bool bound") << QJSValue(engine, false);
3158     QTest::newRow("int bound") << QJSValue(engine, 123);
3159     QTest::newRow("string bound") << QJSValue(engine, QString::fromLatin1("ciao"));
3160     QTest::newRow("undefined bound") << engine->undefinedValue();
3161     QTest::newRow("null bound") << engine->nullValue();
3162 }
3163
3164 void tst_QJSValue::construct_nonFunction()
3165 {
3166     QFETCH(QJSValue, value);
3167     QVERIFY(!value.callAsConstructor().isValid());
3168 }
3169
3170 void tst_QJSValue::construct_simple()
3171 {
3172     QJSEngine eng;
3173     QJSValue fun = eng.evaluate("(function () { this.foo = 123; })");
3174     QVERIFY(fun.isCallable());
3175     QJSValue ret = fun.callAsConstructor();
3176     QVERIFY(ret.isObject());
3177     QVERIFY(ret.instanceOf(fun));
3178     QCOMPARE(ret.property("foo").toInt(), 123);
3179 }
3180
3181 void tst_QJSValue::construct_newObjectJS()
3182 {
3183     QJSEngine eng;
3184     // returning a different object overrides the default-constructed one
3185     QJSValue fun = eng.evaluate("(function () { return { bar: 456 }; })");
3186     QVERIFY(fun.isCallable());
3187     QJSValue ret = fun.callAsConstructor();
3188     QVERIFY(ret.isObject());
3189     QVERIFY(!ret.instanceOf(fun));
3190     QCOMPARE(ret.property("bar").toInt(), 456);
3191 }
3192
3193 #if 0 // FIXME: no c-style callbacks
3194 void tst_QJSValue::construct_undefined()
3195 {
3196     QScriptEngine eng;
3197     QJSValue fun = eng.newFunction(ctorReturningUndefined);
3198     QJSValue ret = fun.callAsConstructor();
3199     QVERIFY(ret.isObject());
3200     QVERIFY(ret.instanceOf(fun));
3201     QCOMPARE(ret.property("foo").toInt(), 123);
3202 }
3203
3204 void tst_QJSValue::construct_newObjectCpp()
3205 {
3206     QScriptEngine eng;
3207     QJSValue fun = eng.newFunction(ctorReturningNewObject);
3208     QJSValue ret = fun.callAsConstructor();
3209     QVERIFY(ret.isObject());
3210     QVERIFY(!ret.instanceOf(fun));
3211     QCOMPARE(ret.property("bar").toInt(), 456);
3212 }
3213 #endif
3214
3215 void tst_QJSValue::construct_arg()
3216 {
3217     QJSEngine eng;
3218     QJSValue Number = eng.evaluate("Number");
3219     QCOMPARE(Number.isCallable(), true);
3220     QJSValueList args;
3221     args << QJSValue(&eng, 123);
3222     QJSValue ret = Number.callAsConstructor(args);
3223     QCOMPARE(ret.isObject(), true);
3224     QCOMPARE(ret.toNumber(), args.at(0).toNumber());
3225 }
3226
3227 void tst_QJSValue::construct_proto()
3228 {
3229     QJSEngine eng;
3230     // test that internal prototype is set correctly
3231     QJSValue fun = eng.evaluate("(function() { return this.__proto__; })");
3232     QCOMPARE(fun.isCallable(), true);
3233     QCOMPARE(fun.property("prototype").isObject(), true);
3234     QJSValue ret = fun.callAsConstructor();
3235     QCOMPARE(fun.property("prototype").strictlyEquals(ret), true);
3236 }
3237
3238 void tst_QJSValue::construct_returnInt()
3239 {
3240     QJSEngine eng;
3241     // test that we return the new object even if a non-object value is returned from the function
3242     QJSValue fun = eng.evaluate("(function() { return 123; })");
3243     QCOMPARE(fun.isCallable(), true);
3244     QJSValue ret = fun.callAsConstructor();
3245     QCOMPARE(ret.isObject(), true);
3246 }
3247
3248 void tst_QJSValue::construct_throw()
3249 {
3250     QJSEngine eng;
3251     QJSValue fun = eng.evaluate("(function() { throw new Error('foo'); })");
3252     QCOMPARE(fun.isCallable(), true);
3253     QJSValue ret = fun.callAsConstructor();
3254     QCOMPARE(ret.isError(), true);
3255     QCOMPARE(eng.hasUncaughtException(), true);
3256     QVERIFY(ret.strictlyEquals(eng.uncaughtException()));
3257 }
3258
3259 #if 0 // FIXME: The feature of interpreting an array as argument list has been removed from the API
3260 void tst_QJSValue::construct()
3261 {
3262     QScriptEngine eng;
3263     QJSValue fun = eng.evaluate("(function() { return arguments; })");
3264     QVERIFY(fun.isCallable());
3265     QJSValue array = eng.newArray(3);
3266     array.setProperty(0, QJSValue(&eng, 123.0));
3267     array.setProperty(1, QJSValue(&eng, 456.0));
3268     array.setProperty(2, QJSValue(&eng, 789.0));
3269     // construct with single array object as arguments
3270     QJSValue ret = fun.callAsConstructor(array);
3271     QVERIFY(!eng.hasUncaughtException());
3272     QVERIFY(ret.isValid());
3273     QVERIFY(ret.isObject());
3274     QCOMPARE(ret.property(0).strictlyEquals(array.property(0)), true);
3275     QCOMPARE(ret.property(1).strictlyEquals(array.property(1)), true);
3276     QCOMPARE(ret.property(2).strictlyEquals(array.property(2)), true);
3277     // construct with arguments object as arguments
3278     QJSValue ret2 = fun.callAsConstructor(ret);
3279     QCOMPARE(ret2.property(0).strictlyEquals(ret.property(0)), true);
3280     QCOMPARE(ret2.property(1).strictlyEquals(ret.property(1)), true);
3281     QCOMPARE(ret2.property(2).strictlyEquals(ret.property(2)), true);
3282     // construct with null as arguments
3283     QJSValue ret3 = fun.callAsConstructor(eng.nullValue());
3284     QCOMPARE(ret3.isError(), false);
3285     QCOMPARE(ret3.property("length").isNumber(), true);
3286     QCOMPARE(ret3.property("length").toNumber(), 0.0);
3287     // construct with undefined as arguments
3288     QJSValue ret4 = fun.callAsConstructor(eng.undefinedValue());
3289     QCOMPARE(ret4.isError(), false);
3290     QCOMPARE(ret4.property("length").isNumber(), true);
3291     QCOMPARE(ret4.property("length").toNumber(), 0.0);
3292     // construct with something else as arguments
3293     QJSValue ret5 = fun.callAsConstructor(QJSValue(&eng, 123.0));
3294     QCOMPARE(ret5.isError(), true);
3295     // construct with a non-array object as arguments
3296     QJSValue ret6 = fun.callAsConstructor(eng.globalObject());
3297     QVERIFY(ret6.isError());
3298     QCOMPARE(ret6.toString(), QString::fromLatin1("TypeError: Arguments must be an array"));
3299 }
3300 #endif
3301
3302 void tst_QJSValue::construct_twoEngines()
3303 {
3304     QJSEngine engine;
3305     QJSEngine otherEngine;
3306     QJSValue ctor = engine.evaluate("(function (a, b) { this.foo = 123; })");
3307     QJSValue arg(&otherEngine, 124567);
3308     QTest::ignoreMessage(QtWarningMsg, "QJSValue::callAsConstructor() failed: cannot construct function with argument created in a different engine");
3309     QVERIFY(!ctor.callAsConstructor(QJSValueList() << arg).isValid());
3310     QTest::ignoreMessage(QtWarningMsg, "QJSValue::callAsConstructor() failed: cannot construct function with argument created in a different engine");
3311     QVERIFY(!ctor.callAsConstructor(QJSValueList() << arg << otherEngine.newObject()).isValid());
3312 }
3313
3314 void tst_QJSValue::construct_constructorThrowsPrimitive()
3315 {
3316     QJSEngine eng;
3317     QJSValue fun = eng.evaluate("(function() { throw 123; })");
3318     QVERIFY(fun.isCallable());
3319     // construct(QJSValueList)
3320     {
3321         QJSValue ret = fun.callAsConstructor();
3322         QVERIFY(ret.isNumber());
3323         QCOMPARE(ret.toNumber(), 123.0);
3324         QVERIFY(eng.hasUncaughtException());
3325         QVERIFY(ret.strictlyEquals(eng.uncaughtException()));
3326         eng.clearExceptions();
3327     }
3328 #if 0 // FIXME: The feature of interpreting an array as argument list has been removed from the API
3329     // construct(QJSValue)
3330     {
3331         QJSValue ret = fun.callAsConstructor(eng.newArray());
3332         QVERIFY(ret.isNumber());
3333         QCOMPARE(ret.toNumber(), 123.0);
3334         QVERIFY(eng.hasUncaughtException());
3335         QVERIFY(ret.strictlyEquals(eng.uncaughtException()));
3336         eng.clearExceptions();
3337     }
3338 #endif
3339 }
3340
3341 #if 0 // FIXME: No QJSValue::lessThan
3342 void tst_QJSValue::lessThan()
3343 {
3344     QScriptEngine eng;
3345
3346     QVERIFY(!QJSValue().lessThan(QJSValue()));
3347
3348     QJSValue num = QJSValue(&eng, 123);
3349     QCOMPARE(num.lessThan(QJSValue(&eng, 124)), true);
3350     QCOMPARE(num.lessThan(QJSValue(&eng, 122)), false);
3351     QCOMPARE(num.lessThan(QJSValue(&eng, 123)), false);
3352     QCOMPARE(num.lessThan(QJSValue(&eng, "124")), true);
3353     QCOMPARE(num.lessThan(QJSValue(&eng, "122")), false);
3354     QCOMPARE(num.lessThan(QJSValue(&eng, "123")), false);
3355     QCOMPARE(num.lessThan(QJSValue(&eng, qSNaN())), false);
3356     QCOMPARE(num.lessThan(QJSValue(&eng, +qInf())), true);
3357     QCOMPARE(num.lessThan(QJSValue(&eng, -qInf())), false);
3358     QCOMPARE(num.lessThan(num), false);
3359     QCOMPARE(num.lessThan(QJSValue(&eng, 124).toObject()), true);
3360     QCOMPARE(num.lessThan(QJSValue(&eng, 122).toObject()), false);
3361     QCOMPARE(num.lessThan(QJSValue(&eng, 123).toObject()), false);
3362     QCOMPARE(num.lessThan(QJSValue(&eng, "124").toObject()), true);
3363     QCOMPARE(num.lessThan(QJSValue(&eng, "122").toObject()), false);
3364     QCOMPARE(num.lessThan(QJSValue(&eng, "123").toObject()), false);
3365     QCOMPARE(num.lessThan(QJSValue(&eng, qSNaN()).toObject()), false);
3366     QCOMPARE(num.lessThan(QJSValue(&eng, +qInf()).toObject()), true);
3367     QCOMPARE(num.lessThan(QJSValue(&eng, -qInf()).toObject()), false);
3368     QCOMPARE(num.lessThan(num.toObject()), false);
3369     QCOMPARE(num.lessThan(QJSValue()), false);
3370
3371     QJSValue str = QJSValue(&eng, "123");
3372     QCOMPARE(str.lessThan(QJSValue(&eng, "124")), true);
3373     QCOMPARE(str.lessThan(QJSValue(&eng, "122")), false);
3374     QCOMPARE(str.lessThan(QJSValue(&eng, "123")), false);
3375     QCOMPARE(str.lessThan(QJSValue(&eng, 124)), true);
3376     QCOMPARE(str.lessThan(QJSValue(&eng, 122)), false);
3377     QCOMPARE(str.lessThan(QJSValue(&eng, 123)), false);
3378     QCOMPARE(str.lessThan(str), false);
3379     QCOMPARE(str.lessThan(QJSValue(&eng, "124").toObject()), true);
3380     QCOMPARE(str.lessThan(QJSValue(&eng, "122").toObject()), false);
3381     QCOMPARE(str.lessThan(QJSValue(&eng, "123").toObject()), false);
3382     QCOMPARE(str.lessThan(QJSValue(&eng, 124).toObject()), true);
3383     QCOMPARE(str.lessThan(QJSValue(&eng, 122).toObject()), false);
3384     QCOMPARE(str.lessThan(QJSValue(&eng, 123).toObject()), false);
3385     QCOMPARE(str.lessThan(str.toObject()), false);
3386     QCOMPARE(str.lessThan(QJSValue()), false);
3387
3388     // V2 constructors
3389     QJSValue num2 = QJSValue(123);
3390     QCOMPARE(num2.lessThan(QJSValue(124)), true);
3391     QCOMPARE(num2.lessThan(QJSValue(122)), false);
3392     QCOMPARE(num2.lessThan(QJSValue(123)), false);
3393     QCOMPARE(num2.lessThan(QJSValue("124")), true);
3394     QCOMPARE(num2.lessThan(QJSValue("122")), false);
3395     QCOMPARE(num2.lessThan(QJSValue("123")), false);
3396     QCOMPARE(num2.lessThan(QJSValue(qSNaN())), false);
3397     QCOMPARE(num2.lessThan(QJSValue(+qInf())), true);
3398     QCOMPARE(num2.lessThan(QJSValue(-qInf())), false);
3399     QCOMPARE(num2.lessThan(num), false);
3400     QCOMPARE(num2.lessThan(QJSValue()), false);
3401
3402     QJSValue str2 = QJSValue("123");
3403     QCOMPARE(str2.lessThan(QJSValue("124")), true);
3404     QCOMPARE(str2.lessThan(QJSValue("122")), false);
3405     QCOMPARE(str2.lessThan(QJSValue("123")), false);
3406     QCOMPARE(str2.lessThan(QJSValue(124)), true);
3407     QCOMPARE(str2.lessThan(QJSValue(122)), false);
3408     QCOMPARE(str2.lessThan(QJSValue(123)), false);
3409     QCOMPARE(str2.lessThan(str), false);
3410     QCOMPARE(str2.lessThan(QJSValue()), false);
3411
3412     QJSValue obj1 = eng.newObject();
3413     QJSValue obj2 = eng.newObject();
3414     QCOMPARE(obj1.lessThan(obj2), false);
3415     QCOMPARE(obj2.lessThan(obj1), false);
3416     QCOMPARE(obj1.lessThan(obj1), false);
3417     QCOMPARE(obj2.lessThan(obj2), false);
3418
3419     QJSValue date1 = eng.newDate(QDateTime(QDate(2000, 1, 1)));
3420     QJSValue date2 = eng.newDate(QDateTime(QDate(1999, 1, 1)));
3421     QCOMPARE(date1.lessThan(date2), false);
3422     QCOMPARE(date2.lessThan(date1), true);
3423     QCOMPARE(date1.lessThan(date1), false);
3424     QCOMPARE(date2.lessThan(date2), false);
3425     QCOMPARE(date1.lessThan(QJSValue()), false);
3426
3427     QCOMPARE(QJSValue().lessThan(date2), false);
3428
3429     QScriptEngine otherEngine;
3430     QTest::ignoreMessage(QtWarningMsg, "QJSValue::lessThan: "
3431                          "cannot compare to a value created in "
3432                          "a different engine");
3433     QCOMPARE(date1.lessThan(QJSValue(&otherEngine, 123)), false);
3434 }
3435 #endif
3436
3437 void tst_QJSValue::equals()
3438 {
3439     QJSEngine eng;
3440
3441     QVERIFY(QJSValue().equals(QJSValue()));
3442
3443     QJSValue num = QJSValue(&eng, 123);
3444     QCOMPARE(num.equals(QJSValue(&eng, 123)), true);
3445     QCOMPARE(num.equals(QJSValue(&eng, 321)), false);
3446     QCOMPARE(num.equals(QJSValue(&eng, QLatin1String("123"))), true);
3447     QCOMPARE(num.equals(QJSValue(&eng, QLatin1String("321"))), false);
3448     QCOMPARE(num.equals(QJSValue(&eng, 123).toObject()), true);
3449     QCOMPARE(num.equals(QJSValue(&eng, 321).toObject()), false);
3450     QCOMPARE(num.equals(QJSValue(&eng, QLatin1String("123")).toObject()), true);
3451     QCOMPARE(num.equals(QJSValue(&eng, QLatin1String("321")).toObject()), false);
3452     QVERIFY(num.toObject().equals(num));
3453     QCOMPARE(num.equals(QJSValue()), false);
3454
3455     QJSValue str = QJSValue(&eng, QLatin1String("123"));
3456     QCOMPARE(str.equals(QJSValue(&eng, QLatin1String("123"))), true);
3457     QCOMPARE(str.equals(QJSValue(&eng, QLatin1String("321"))), false);
3458     QCOMPARE(str.equals(QJSValue(&eng, 123)), true);
3459     QCOMPARE(str.equals(QJSValue(&eng, 321)), false);
3460     QCOMPARE(str.equals(QJSValue(&eng, QLatin1String("123")).toObject()), true);
3461     QCOMPARE(str.equals(QJSValue(&eng, QLatin1String("321")).toObject()), false);
3462     QCOMPARE(str.equals(QJSValue(&eng, 123).toObject()), true);
3463     QCOMPARE(str.equals(QJSValue(&eng, 321).toObject()), false);
3464     QVERIFY(str.toObject().equals(str));
3465     QCOMPARE(str.equals(QJSValue()), false);
3466
3467     QJSValue num2 = QJSValue(123);
3468     QCOMPARE(num2.equals(QJSValue(123)), true);
3469     QCOMPARE(num2.equals(QJSValue(321)), false);
3470     QCOMPARE(num2.equals(QJSValue("123")), true);
3471     QCOMPARE(num2.equals(QJSValue("321")), false);
3472     QCOMPARE(num2.equals(QJSValue()), false);
3473
3474     QJSValue str2 = QJSValue("123");
3475     QCOMPARE(str2.equals(QJSValue("123")), true);
3476     QCOMPARE(str2.equals(QJSValue("321")), false);
3477     QCOMPARE(str2.equals(QJSValue(123)), true);
3478     QCOMPARE(str2.equals(QJSValue(321)), false);
3479     QCOMPARE(str2.equals(QJSValue()), false);
3480
3481     QJSValue date1 = eng.newDate(QDateTime(QDate(2000, 1, 1)));
3482     QJSValue date2 = eng.newDate(QDateTime(QDate(1999, 1, 1)));
3483     QCOMPARE(date1.equals(date2), false);
3484     QCOMPARE(date1.equals(date1), true);
3485     QCOMPARE(date2.equals(date2), true);
3486
3487     QJSValue undefined = eng.undefinedValue();
3488     QJSValue null = eng.nullValue();
3489     QCOMPARE(undefined.equals(undefined), true);
3490     QCOMPARE(null.equals(null), true);
3491     QCOMPARE(undefined.equals(null), true);
3492     QCOMPARE(null.equals(undefined), true);
3493     QCOMPARE(undefined.equals(QJSValue()), false);
3494     QCOMPARE(null.equals(QJSValue()), false);
3495     QVERIFY(!null.equals(num));
3496     QVERIFY(!undefined.equals(num));
3497
3498     QJSValue sant = QJSValue(&eng, true);
3499     QVERIFY(sant.equals(QJSValue(&eng, 1)));
3500     QVERIFY(sant.equals(QJSValue(&eng, QLatin1String("1"))));
3501     QVERIFY(sant.equals(sant));
3502     QVERIFY(sant.equals(QJSValue(&eng, 1).toObject()));
3503     QVERIFY(sant.equals(QJSValue(&eng, QLatin1String("1")).toObject()));
3504     QVERIFY(sant.equals(sant.toObject()));
3505     QVERIFY(sant.toObject().equals(sant));
3506     QVERIFY(!sant.equals(QJSValue(&eng, 0)));
3507     QVERIFY(!sant.equals(undefined));
3508     QVERIFY(!sant.equals(null));
3509
3510     QJSValue falskt = QJSValue(&eng, false);
3511     QVERIFY(falskt.equals(QJSValue(&eng, 0)));
3512     QVERIFY(falskt.equals(QJSValue(&eng, QLatin1String("0"))));
3513     QVERIFY(falskt.equals(falskt));
3514     QVERIFY(falskt.equals(QJSValue(&eng, 0).toObject()));
3515     QVERIFY(falskt.equals(QJSValue(&eng, QLatin1String("0")).toObject()));
3516     QVERIFY(falskt.equals(falskt.toObject()));
3517     QVERIFY(falskt.toObject().equals(falskt));
3518     QVERIFY(!falskt.equals(sant));
3519     QVERIFY(!falskt.equals(undefined));
3520     QVERIFY(!falskt.equals(null));
3521
3522     QJSValue obj1 = eng.newObject();
3523     QJSValue obj2 = eng.newObject();
3524     QCOMPARE(obj1.equals(obj2), false);
3525     QCOMPARE(obj2.equals(obj1), false);
3526     QCOMPARE(obj1.equals(obj1), true);
3527     QCOMPARE(obj2.equals(obj2), true);
3528
3529     QJSValue qobj1 = eng.newQObject(this);
3530     QJSValue qobj2 = eng.newQObject(this);
3531     QJSValue qobj3 = eng.newQObject(0);
3532
3533     // FIXME: No ScriptOwnership: QJSValue qobj4 = eng.newQObject(new QObject(), QScriptEngine::ScriptOwnership);
3534     QJSValue qobj4 = eng.newQObject(new QObject());
3535
3536     QVERIFY(qobj1.equals(qobj2)); // compares the QObject pointers
3537     QVERIFY(!qobj2.equals(qobj4)); // compares the QObject pointers
3538     QVERIFY(!qobj2.equals(obj2)); // compares the QObject pointers
3539
3540     QJSValue compareFun = eng.evaluate("(function(a, b) { return a == b; })");
3541     QVERIFY(compareFun.isCallable());
3542     {
3543         QJSValue ret = compareFun.call(QJSValueList() << qobj1 << qobj2);
3544         QVERIFY(ret.isBool());
3545         ret = compareFun.call(QJSValueList() << qobj1 << qobj3);
3546         QVERIFY(ret.isBool());
3547         QVERIFY(!ret.toBool());
3548         ret = compareFun.call(QJSValueList() << qobj1 << qobj4);
3549         QVERIFY(ret.isBool());
3550         QVERIFY(!ret.toBool());
3551         ret = compareFun.call(QJSValueList() << qobj1 << obj1);
3552         QVERIFY(ret.isBool());
3553         QVERIFY(!ret.toBool());
3554     }
3555
3556     {
3557         QJSValue var1 = eng.newVariant(QVariant(false));
3558         QJSValue var2 = eng.newVariant(QVariant(false));
3559         QEXPECT_FAIL("", "FIXME: QVariant comparison does not work with v8", Continue);
3560         QVERIFY(var1.equals(var2));
3561         {
3562             QJSValue ret = compareFun.call(QJSValue(), QJSValueList() << var1 << var2);
3563             QVERIFY(ret.isBool());
3564         }
3565     }
3566     {
3567         QJSValue var1 = eng.newVariant(QVariant(false));
3568         QJSValue var2 = eng.newVariant(QVariant(0));
3569         // QVariant::operator==() performs type conversion
3570         QEXPECT_FAIL("", "FIXME: QVariant comparison does not work with v8", Continue);
3571         QVERIFY(var1.equals(var2));
3572     }
3573     {
3574         QJSValue var1 = eng.newVariant(QVariant(QStringList() << "a"));
3575         QJSValue var2 = eng.newVariant(QVariant(QStringList() << "a"));
3576         QEXPECT_FAIL("", "FIXME: QVariant comparison does not work with v8", Continue);
3577         QVERIFY(var1.equals(var2));
3578     }
3579     {
3580         QJSValue var1 = eng.newVariant(QVariant(QStringList() << "a"));
3581         QJSValue var2 = eng.newVariant(QVariant(QStringList() << "b"));
3582         QVERIFY(!var1.equals(var2));
3583     }
3584     {
3585         QJSValue var1 = eng.newVariant(QVariant(QPoint(1, 2)));
3586         QJSValue var2 = eng.newVariant(QVariant(QPoint(1, 2)));
3587         QEXPECT_FAIL("", "FIXME: QVariant comparison does not work with v8", Continue);
3588         QVERIFY(var1.equals(var2));
3589     }
3590     {
3591         QJSValue var1 = eng.newVariant(QVariant(QPoint(1, 2)));
3592         QJSValue var2 = eng.newVariant(QVariant(QPoint(3, 4)));
3593         QVERIFY(!var1.equals(var2));
3594     }
3595     {
3596         QJSValue var1 = eng.newVariant(QVariant(int(1)));
3597         QJSValue var2 = eng.newVariant(QVariant(double(1)));
3598         // QVariant::operator==() performs type conversion
3599         QEXPECT_FAIL("", "FIXME: QVariant comparison does not work with v8", Continue);
3600         QVERIFY(var1.equals(var2));
3601     }
3602     {
3603         QJSValue var1 = eng.newVariant(QVariant(QString::fromLatin1("123")));
3604         QJSValue var2 = eng.newVariant(QVariant(double(123)));
3605         QJSValue var3(QString::fromLatin1("123"));
3606         QJSValue var4(123);
3607
3608         QVERIFY(var1.equals(var1));
3609         QEXPECT_FAIL("", "FIXME: QVariant comparison does not work with v8", Continue);
3610         QVERIFY(var1.equals(var2));
3611         QVERIFY(var1.equals(var3));
3612         QVERIFY(var1.equals(var4));
3613
3614         QEXPECT_FAIL("", "FIXME: QVariant comparison does not work with v8", Continue);
3615         QVERIFY(var2.equals(var1));
3616         QVERIFY(var2.equals(var2));
3617         QVERIFY(var2.equals(var3));
3618         QVERIFY(var2.equals(var4));
3619
3620         QVERIFY(var3.equals(var1));
3621         QVERIFY(var3.equals(var2));
3622         QVERIFY(var3.equals(var3));
3623         QVERIFY(var3.equals(var4));
3624
3625         QVERIFY(var4.equals(var1));
3626         QVERIFY(var4.equals(var2));
3627         QVERIFY(var4.equals(var3));
3628         QVERIFY(var4.equals(var4));
3629     }
3630
3631     QJSEngine otherEngine;
3632     QTest::ignoreMessage(QtWarningMsg, "QJSValue::equals: "
3633                          "cannot compare to a value created in "
3634                          "a different engine");
3635     QCOMPARE(date1.equals(QJSValue(&otherEngine, 123)), false);
3636 }
3637
3638 void tst_QJSValue::strictlyEquals()
3639 {
3640     QJSEngine eng;
3641
3642     QVERIFY(QJSValue().strictlyEquals(QJSValue()));
3643
3644     QJSValue num = QJSValue(&eng, 123);
3645     QCOMPARE(num.strictlyEquals(QJSValue(&eng, 123)), true);
3646     QCOMPARE(num.strictlyEquals(QJSValue(&eng, 321)), false);
3647     QCOMPARE(num.strictlyEquals(QJSValue(&eng, QLatin1String("123"))), false);
3648     QCOMPARE(num.strictlyEquals(QJSValue(&eng, QLatin1String("321"))), false);
3649     QCOMPARE(num.strictlyEquals(QJSValue(&eng, 123).toObject()), false);
3650     QCOMPARE(num.strictlyEquals(QJSValue(&eng, 321).toObject()), false);
3651     QCOMPARE(num.strictlyEquals(QJSValue(&eng, QLatin1String("123")).toObject()), false);
3652     QCOMPARE(num.strictlyEquals(QJSValue(&eng, QLatin1String("321")).toObject()), false);
3653     QVERIFY(!num.toObject().strictlyEquals(num));
3654     QVERIFY(!num.strictlyEquals(QJSValue()));
3655     QVERIFY(!QJSValue().strictlyEquals(num));
3656
3657     QJSValue str = QJSValue(&eng, QLatin1String("123"));
3658     QCOMPARE(str.strictlyEquals(QJSValue(&eng, QLatin1String("123"))), true);
3659     QCOMPARE(str.strictlyEquals(QJSValue(&eng, QLatin1String("321"))), false);
3660     QCOMPARE(str.strictlyEquals(QJSValue(&eng, 123)), false);
3661     QCOMPARE(str.strictlyEquals(QJSValue(&eng, 321)), false);
3662     QCOMPARE(str.strictlyEquals(QJSValue(&eng, QLatin1String("123")).toObject()), false);
3663     QCOMPARE(str.strictlyEquals(QJSValue(&eng, QLatin1String("321")).toObject()), false);
3664     QCOMPARE(str.strictlyEquals(QJSValue(&eng, 123).toObject()), false);
3665     QCOMPARE(str.strictlyEquals(QJSValue(&eng, 321).toObject()), false);
3666     QVERIFY(!str.toObject().strictlyEquals(str));
3667     QVERIFY(!str.strictlyEquals(QJSValue()));
3668
3669     QJSValue num2 = QJSValue(123);
3670     QCOMPARE(num2.strictlyEquals(QJSValue(123)), true);
3671     QCOMPARE(num2.strictlyEquals(QJSValue(321)), false);
3672     QCOMPARE(num2.strictlyEquals(QJSValue("123")), false);
3673     QCOMPARE(num2.strictlyEquals(QJSValue("321")), false);
3674     QVERIFY(!num2.strictlyEquals(QJSValue()));
3675
3676     QJSValue str2 = QJSValue("123");
3677     QCOMPARE(str2.strictlyEquals(QJSValue("123")), true);
3678     QCOMPARE(str2.strictlyEquals(QJSValue("321")), false);
3679     QCOMPARE(str2.strictlyEquals(QJSValue(123)), false);
3680     QCOMPARE(str2.strictlyEquals(QJSValue(321)), false);
3681     QVERIFY(!str2.strictlyEquals(QJSValue()));
3682
3683     QJSValue date1 = eng.newDate(QDateTime(QDate(2000, 1, 1)));
3684     QJSValue date2 = eng.newDate(QDateTime(QDate(1999, 1, 1)));
3685     QCOMPARE(date1.strictlyEquals(date2), false);
3686     QCOMPARE(date1.strictlyEquals(date1), true);
3687     QCOMPARE(date2.strictlyEquals(date2), true);
3688     QVERIFY(!date1.strictlyEquals(QJSValue()));
3689
3690     QJSValue undefined = eng.undefinedValue();
3691     QJSValue null = eng.nullValue();
3692     QCOMPARE(undefined.strictlyEquals(undefined), true);
3693     QCOMPARE(null.strictlyEquals(null), true);
3694     QCOMPARE(undefined.strictlyEquals(null), false);
3695     QCOMPARE(null.strictlyEquals(undefined), false);
3696     QVERIFY(!null.strictlyEquals(QJSValue()));
3697
3698     QJSValue sant = QJSValue(&eng, true);
3699     QVERIFY(!sant.strictlyEquals(QJSValue(&eng, 1)));
3700     QVERIFY(!sant.strictlyEquals(QJSValue(&eng, QLatin1String("1"))));
3701     QVERIFY(sant.strictlyEquals(sant));
3702     QVERIFY(!sant.strictlyEquals(QJSValue(&eng, 1).toObject()));
3703     QVERIFY(!sant.strictlyEquals(QJSValue(&eng, QLatin1String("1")).toObject()));
3704     QVERIFY(!sant.strictlyEquals(sant.toObject()));
3705     QVERIFY(!sant.toObject().strictlyEquals(sant));
3706     QVERIFY(!sant.strictlyEquals(QJSValue(&eng, 0)));
3707     QVERIFY(!sant.strictlyEquals(undefined));
3708     QVERIFY(!sant.strictlyEquals(null));
3709     QVERIFY(!sant.strictlyEquals(QJSValue()));
3710
3711     QJSValue falskt = QJSValue(&eng, false);
3712     QVERIFY(!falskt.strictlyEquals(QJSValue(&eng, 0)));
3713     QVERIFY(!falskt.strictlyEquals(QJSValue(&eng, QLatin1String("0"))));
3714     QVERIFY(falskt.strictlyEquals(falskt));
3715     QVERIFY(!falskt.strictlyEquals(QJSValue(&eng, 0).toObject()));
3716     QVERIFY(!falskt.strictlyEquals(QJSValue(&eng, QLatin1String("0")).toObject()));
3717     QVERIFY(!falskt.strictlyEquals(falskt.toObject()));
3718     QVERIFY(!falskt.toObject().strictlyEquals(falskt));
3719     QVERIFY(!falskt.strictlyEquals(sant));
3720     QVERIFY(!falskt.strictlyEquals(undefined));
3721     QVERIFY(!falskt.strictlyEquals(null));
3722     QVERIFY(!falskt.strictlyEquals(QJSValue()));
3723
3724     QVERIFY(!QJSValue(false).strictlyEquals(123));
3725     QVERIFY(!QJSValue(QJSValue::UndefinedValue).strictlyEquals(123));
3726     QVERIFY(!QJSValue(QJSValue::NullValue).strictlyEquals(123));
3727     QVERIFY(!QJSValue(false).strictlyEquals("ciao"));
3728     QVERIFY(!QJSValue(QJSValue::UndefinedValue).strictlyEquals("ciao"));
3729     QVERIFY(!QJSValue(QJSValue::NullValue).strictlyEquals("ciao"));
3730     QVERIFY(QJSValue(&eng, QLatin1String("ciao")).strictlyEquals("ciao"));
3731     QVERIFY(QJSValue("ciao").strictlyEquals(QJSValue(&eng, QLatin1String("ciao"))));
3732     QVERIFY(!QJSValue("ciao").strictlyEquals(123));
3733     QVERIFY(!QJSValue("ciao").strictlyEquals(QJSValue(&eng, 123)));
3734     QVERIFY(!QJSValue(123).strictlyEquals("ciao"));
3735     QVERIFY(!QJSValue(123).strictlyEquals(QJSValue(&eng, QLatin1String("ciao"))));
3736     QVERIFY(!QJSValue(&eng, 123).strictlyEquals("ciao"));
3737
3738     QJSValue obj1 = eng.newObject();
3739     QJSValue obj2 = eng.newObject();
3740     QCOMPARE(obj1.strictlyEquals(obj2), false);
3741     QCOMPARE(obj2.strictlyEquals(obj1), false);
3742     QCOMPARE(obj1.strictlyEquals(obj1), true);
3743     QCOMPARE(obj2.strictlyEquals(obj2), true);
3744     QVERIFY(!obj1.strictlyEquals(QJSValue()));
3745
3746     QJSValue qobj1 = eng.newQObject(this);
3747     QJSValue qobj2 = eng.newQObject(this);
3748     QVERIFY(qobj1.strictlyEquals(qobj2));
3749
3750     {
3751         QJSValue var1 = eng.newVariant(QVariant(false));
3752         QJSValue var2 = eng.newVariant(QVariant(false));
3753         QVERIFY(!var1.strictlyEquals(var2));
3754         QVERIFY(!var1.strictlyEquals(QJSValue()));
3755     }
3756     {
3757         QJSValue var1 = eng.newVariant(QVariant(false));
3758         QJSValue var2 = eng.newVariant(QVariant(0));
3759         QVERIFY(!var1.strictlyEquals(var2));
3760     }
3761     {
3762         QJSValue var1 = eng.newVariant(QVariant(QStringList() << "a"));
3763         QJSValue var2 = eng.newVariant(QVariant(QStringList() << "a"));
3764         QVERIFY(!var1.strictlyEquals(var2));
3765     }
3766     {
3767         QJSValue var1 = eng.newVariant(QVariant(QStringList() << "a"));
3768         QJSValue var2 = eng.newVariant(QVariant(QStringList() << "b"));
3769         QVERIFY(!var1.strictlyEquals(var2));
3770     }
3771     {
3772         QJSValue var1 = eng.newVariant(QVariant(QPoint(1, 2)));
3773         QJSValue var2 = eng.newVariant(QVariant(QPoint(1, 2)));
3774         QVERIFY(!var1.strictlyEquals(var2));
3775     }
3776     {
3777         QJSValue var1 = eng.newVariant(QVariant(QPoint(1, 2)));
3778         QJSValue var2 = eng.newVariant(QVariant(QPoint(3, 4)));
3779         QVERIFY(!var1.strictlyEquals(var2));
3780     }
3781
3782     QJSEngine otherEngine;
3783     QTest::ignoreMessage(QtWarningMsg, "QJSValue::strictlyEquals: "
3784                          "cannot compare to a value created in "
3785                          "a different engine");
3786     QCOMPARE(date1.strictlyEquals(QJSValue(&otherEngine, 123)), false);
3787 }
3788
3789 Q_DECLARE_METATYPE(int*)
3790 Q_DECLARE_METATYPE(double*)
3791 Q_DECLARE_METATYPE(QColor*)
3792 Q_DECLARE_METATYPE(QBrush*)
3793
3794 void tst_QJSValue::castToPointer()
3795 {
3796     QJSEngine eng;
3797     {
3798         QJSValue v = eng.newVariant(int(123));
3799         int *ip = qjsvalue_cast<int*>(v);
3800         QVERIFY(ip != 0);
3801         QCOMPARE(*ip, 123);
3802         *ip = 456;
3803         QCOMPARE(qjsvalue_cast<int>(v), 456);
3804
3805         double *dp = qjsvalue_cast<double*>(v);
3806         QVERIFY(dp == 0);
3807
3808         QJSValue v2 = eng.newVariant(qVariantFromValue(ip));
3809         QCOMPARE(qjsvalue_cast<int*>(v2), ip);
3810     }
3811     {
3812         QColor c(123, 210, 231);
3813         QJSValue v = eng.newVariant(c);
3814         QColor *cp = qjsvalue_cast<QColor*>(v);
3815         QVERIFY(cp != 0);
3816         QCOMPARE(*cp, c);
3817
3818         QBrush *bp = qjsvalue_cast<QBrush*>(v);
3819         QVERIFY(bp == 0);
3820
3821         QJSValue v2 = eng.newVariant(qVariantFromValue(cp));
3822         QCOMPARE(qjsvalue_cast<QColor*>(v2), cp);
3823     }
3824 }
3825
3826 void tst_QJSValue::prettyPrinter_data()
3827 {
3828     QTest::addColumn<QString>("function");
3829     QTest::addColumn<QString>("expected");
3830     QTest::newRow("function() { }") << QString("function() { }") << QString("function () { }");
3831     QTest::newRow("function foo() { }") << QString("(function foo() { })") << QString("function foo() { }");
3832     QTest::newRow("function foo(bar) { }") << QString("(function foo(bar) { })") << QString("function foo(bar) { }");
3833     QTest::newRow("function foo(bar, baz) { }") << QString("(function foo(bar, baz) { })") << QString("function foo(bar, baz) { }");
3834     QTest::newRow("this") << QString("function() { this; }") << QString("function () { this; }");
3835     QTest::newRow("identifier") << QString("function(a) { a; }") << QString("function (a) { a; }");
3836     QTest::newRow("null") << QString("function() { null; }") << QString("function () { null; }");
3837     QTest::newRow("true") << QString("function() { true; }") << QString("function () { true; }");
3838     QTest::newRow("false") << QString("function() { false; }") << QString("function () { false; }");
3839     QTest::newRow("string") << QString("function() { 'test'; }") << QString("function () { \'test\'; }");
3840     QTest::newRow("string") << QString("function() { \"test\"; }") << QString("function () { \"test\"; }");
3841     QTest::newRow("number") << QString("function() { 123; }") << QString("function () { 123; }");
3842     QTest::newRow("number") << QString("function() { 123.456; }") << QString("function () { 123.456; }");
3843     QTest::newRow("regexp") << QString("function() { /hello/; }") << QString("function () { /hello/; }");
3844     QTest::newRow("regexp") << QString("function() { /hello/gim; }") << QString("function () { /hello/gim; }");
3845     QTest::newRow("array") << QString("function() { []; }") << QString("function () { []; }");
3846     QTest::newRow("array") << QString("function() { [10]; }") << QString("function () { [10]; }");
3847     QTest::newRow("array") << QString("function() { [10, 20, 30]; }") << QString("function () { [10, 20, 30]; }");
3848     QTest::newRow("array") << QString("function() { [10, 20, , 40]; }") << QString("function () { [10, 20, , 40]; }");
3849     QTest::newRow("array") << QString("function() { [,]; }") << QString("function () { [,]; }");
3850     QTest::newRow("array") << QString("function() { [, 10]; }") << QString("function () { [, 10]; }");
3851     QTest::newRow("array") << QString("function() { [, 10, ]; }") << QString("function () { [, 10, ]; }");
3852     QTest::newRow("array") << QString("function() { [, 10, ,]; }") << QString("function () { [, 10, ,]; }");
3853     QTest::newRow("array") << QString("function() { [[10], [20]]; }") << QString("function () { [[10], [20]]; }");
3854     QTest::newRow("member") << QString("function() { a.b; }") << QString("function () { a.b; }");
3855     QTest::newRow("member") << QString("function() { a.b.c; }") << QString("function () { a.b.c; }");
3856     QTest::newRow("call") << QString("function() { f(); }") << QString("function () { f(); }");
3857     QTest::newRow("call") << QString("function() { f(a); }") << QString("function () { f(a); }");
3858     QTest::newRow("call") << QString("function() { f(a, b); }") << QString("function () { f(a, b); }");
3859     QTest::newRow("new") << QString("function() { new C(); }") << QString("function () { new C(); }");
3860     QTest::newRow("new") << QString("function() { new C(a); }") << QString("function () { new C(a); }");
3861     QTest::newRow("new") << QString("function() { new C(a, b); }") << QString("function () { new C(a, b); }");
3862     QTest::newRow("++") << QString("function() { a++; }") << QString("function () { a++; }");
3863     QTest::newRow("++") << QString("function() { ++a; }") << QString("function () { ++a; }");
3864     QTest::newRow("--") << QString("function() { a--; }") << QString("function () { a--; }");
3865     QTest::newRow("--") << QString("function() { --a; }") << QString("function () { --a; }");
3866     QTest::newRow("delete") << QString("function() { delete a; }") << QString("function () { delete a; }");
3867     QTest::newRow("void") << QString("function() { void a; }") << QString("function () { void a; }");
3868     QTest::newRow("typeof") << QString("function() { typeof a; }") << QString("function () { typeof a; }");
3869     QTest::newRow("+") << QString("function() { +a; }") << QString("function () { +a; }");
3870     QTest::newRow("-") << QString("function() { -a; }") << QString("function () { -a; }");
3871     QTest::newRow("~") << QString("function() { ~a; }") << QString("function () { ~a; }");
3872     QTest::newRow("!") << QString("function() { !a; }") << QString("function () { !a; }");
3873     QTest::newRow("+") << QString("function() { a + b; }") << QString("function () { a + b; }");
3874     QTest::newRow("&&") << QString("function() { a && b; }") << QString("function () { a && b; }");
3875     QTest::newRow("&=") << QString("function() { a &= b; }") << QString("function () { a &= b; }");
3876     QTest::newRow("=") << QString("function() { a = b; }") << QString("function () { a = b; }");
3877     QTest::newRow("&") << QString("function() { a & b; }") << QString("function () { a & b; }");
3878     QTest::newRow("|") << QString("function() { a | b; }") << QString("function () { a | b; }");
3879     QTest::newRow("^") << QString("function() { a ^ b; }") << QString("function () { a ^ b; }");
3880     QTest::newRow("-=") << QString("function() { a -= b; }") << QString("function () { a -= b; }");
3881     QTest::newRow("/") << QString("function() { a / b; }") << QString("function () { a / b; }");
3882     QTest::newRow("/=") << QString("function() { a /= b; }") << QString("function () { a /= b; }");
3883     QTest::newRow("==") << QString("function() { a == b; }") << QString("function () { a == b; }");
3884     QTest::newRow(">=") << QString("function() { a >= b; }") << QString("function () { a >= b; }");
3885     QTest::newRow(">") << QString("function() { a > b; }") << QString("function () { a > b; }");
3886     QTest::newRow("in") << QString("function() { a in b; }") << QString("function () { a in b; }");
3887     QTest::newRow("+=") << QString("function() { a += b; }") << QString("function () { a += b; }");
3888     QTest::newRow("instanceof") << QString("function() { a instanceof b; }") << QString("function () { a instanceof b; }");
3889     QTest::newRow("<=") << QString("function() { a <= b; }") << QString("function () { a <= b; }");
3890     QTest::newRow("<<") << QString("function() { a << b; }") << QString("function () { a << b; }");
3891     QTest::newRow("<<=") << QString("function() { a <<= b; }") << QString("function () { a <<= b; }");
3892     QTest::newRow("<") << QString("function() { a < b; }") << QString("function () { a < b; }");
3893     QTest::newRow("%") << QString("function() { a % b; }") << QString("function () { a % b; }");
3894     QTest::newRow("%=") << QString("function() { a %= b; }") << QString("function () { a %= b; }");
3895     QTest::newRow("*") << QString("function() { a * b; }") << QString("function () { a * b; }");
3896     QTest::newRow("*=") << QString("function() { a *= b; }") << QString("function () { a *= b; }");
3897     QTest::newRow("!=") << QString("function() { a != b; }") << QString("function () { a != b; }");
3898     QTest::newRow("||") << QString("function() { a || b; }") << QString("function () { a || b; }");
3899     QTest::newRow("|=") << QString("function() { a |= b; }") << QString("function () { a |= b; }");
3900     QTest::newRow(">>") << QString("function() { a >> b; }") << QString("function () { a >> b; }");
3901     QTest::newRow(">>=") << QString("function() { a >>= b; }") << QString("function () { a >>= b; }");
3902     QTest::newRow("===") << QString("function() { a === b; }") << QString("function () { a === b; }");
3903     QTest::newRow("!==") << QString("function() { a !== b; }") << QString("function () { a !== b; }");
3904     QTest::newRow("-") << QString("function() { a - b; }") << QString("function () { a - b; }");
3905     QTest::newRow(">>>") << QString("function() { a >>> b; }") << QString("function () { a >>> b; }");
3906     QTest::newRow(">>>=") << QString("function() { a >>>= b; }") << QString("function () { a >>>= b; }");
3907     QTest::newRow("^=") << QString("function() { a ^= b; }") << QString("function () { a ^= b; }");
3908     QTest::newRow("? :") << QString("function() { a ? b : c; }") << QString("function () { a ? b : c; }");
3909     QTest::newRow("a; b; c") << QString("function() { a; b; c; }") << QString("function () { a; b; c; }");
3910     QTest::newRow("var a;") << QString("function() { var a; }") << QString("function () { var a; }");
3911     QTest::newRow("var a, b;") << QString("function() { var a, b; }") << QString("function () { var a, b; }");
3912     QTest::newRow("var a = 10;") << QString("function() { var a = 10; }") << QString("function () { var a = 10; }");
3913     QTest::newRow("var a, b = 20;") << QString("function() { var a, b = 20; }") << QString("function () { var a, b = 20; }");
3914     QTest::newRow("var a = 10, b = 20;") << QString("function() { var a = 10, b = 20; }") << QString("function () { var a = 10, b = 20; }");
3915     QTest::newRow("if") << QString("function() { if (a) b; }") << QString("function () { if (a) b; }");
3916     QTest::newRow("if") << QString("function() { if (a) { b; c; } }") << QString("function () { if (a) { b; c; } }");
3917     QTest::newRow("if-else") << QString("function() { if (a) b; else c; }") << QString("function () { if (a) b; else c; }");
3918     QTest::newRow("if-else") << QString("function() { if (a) { b; c; } else { d; e; } }") << QString("function () { if (a) { b; c; } else { d; e; } }");
3919     QTest::newRow("do-while") << QString("function() { do { a; } while (b); }") << QString("function () { do { a; } while (b); }");
3920     QTest::newRow("do-while") << QString("function() { do { a; b; c; } while (d); }") << QString("function () { do { a; b; c; } while (d); }");
3921     QTest::newRow("while") << QString("function() { while (a) { b; } }") << QString("function () { while (a) { b; } }");
3922     QTest::newRow("while") << QString("function() { while (a) { b; c; } }") << QString("function () { while (a) { b; c; } }");
3923     QTest::newRow("for") << QString("function() { for (a; b; c) { } }") << QString("function () { for (a; b; c) { } }");
3924     QTest::newRow("for") << QString("function() { for (; a; b) { } }") << QString("function () { for (; a; b) { } }");
3925     QTest::newRow("for") << QString("function() { for (; ; a) { } }") << QString("function () { for (; ; a) { } }");
3926     QTest::newRow("for") << QString("function() { for (; ; ) { } }") << QString("function () { for (; ; ) { } }");
3927     QTest::newRow("for") << QString("function() { for (var a; b; c) { } }") << QString("function () { for (var a; b; c) { } }");
3928     QTest::newRow("for") << QString("function() { for (var a, b, c; d; e) { } }") << QString("function () { for (var a, b, c; d; e) { } }");
3929     QTest::newRow("continue") << QString("function() { for (; ; ) { continue; } }") << QString("function () { for (; ; ) { continue; } }");
3930     QTest::newRow("break") << QString("function() { for (; ; ) { break; } }") << QString("function () { for (; ; ) { break; } }");
3931     QTest::newRow("return") << QString("function() { return; }") << QString("function () { return; }");
3932     QTest::newRow("return") << QString("function() { return 10; }") << QString("function () { return 10; }");
3933     QTest::newRow("with") << QString("function() { with (a) { b; } }") << QString("function () { with (a) { b; } }");
3934     QTest::newRow("with") << QString("function() { with (a) { b; c; } }") << QString("function () { with (a) { b; c; } }");
3935     QTest::newRow("switch") << QString("function() { switch (a) { } }") << QString("function () { switch (a) { } }");
3936     QTest::newRow("switch") << QString("function() { switch (a) { case 1: ; } }") << QString("function () { switch (a) { case 1: ; } }");
3937     QTest::newRow("switch") << QString("function() { switch (a) { case 1: b; break; } }") << QString("function () { switch (a) { case 1: b; break; } }");
3938     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; } }");
3939     QTest::newRow("switch") << QString("function() { switch (a) { case 1: case 2: ; } }") << QString("function () { switch (a) { case 1: case 2: ; } }");
3940     QTest::newRow("switch") << QString("function() { switch (a) { case 1: default: ; } }") << QString("function () { switch (a) { case 1: default: ; } }");
3941     QTest::newRow("switch") << QString("function() { switch (a) { case 1: default: ; case 3: ; } }") << QString("function () { switch (a) { case 1: default: ; case 3: ; } }");
3942     QTest::newRow("label") << QString("function() { a: b; }") << QString("function () { a: b; }");
3943     QTest::newRow("throw") << QString("function() { throw a; }") << QString("function () { throw a; }");
3944     QTest::newRow("try-catch") << QString("function() { try { a; } catch (e) { b; } }") << QString("function () { try { a; } catch (e) { b; } }");
3945     QTest::newRow("try-finally") << QString("function() { try { a; } finally { b; } }") << QString("function () { try { a; } finally { b; } }");
3946     QTest::newRow("try-catch-finally") << QString("function() { try { a; } catch (e) { b; } finally { c; } }") << QString("function () { try { a; } catch (e) { b; } finally { c; } }");
3947     QTest::newRow("a + b + c + d") << QString("function() { a + b + c + d; }") << QString("function () { a + b + c + d; }");
3948     QTest::newRow("a + b - c") << QString("function() { a + b - c; }") << QString("function () { a + b - c; }");
3949     QTest::newRow("a + -b") << QString("function() { a + -b; }") << QString("function () { a + -b; }");
3950     QTest::newRow("a + ~b") << QString("function() { a + ~b; }") << QString("function () { a + ~b; }");
3951     QTest::newRow("a + !b") << QString("function() { a + !b; }") << QString("function () { a + !b; }");
3952     QTest::newRow("a + +b") << QString("function() { a + +b; }") << QString("function () { a + +b; }");
3953     QTest::newRow("(a + b) - c") << QString("function() { (a + b) - c; }") << QString("function () { (a + b) - c; }");
3954     QTest::newRow("(a - b + c") << QString("function() { a - b + c; }") << QString("function () { a - b + c; }");
3955     QTest::newRow("(a - (b + c)") << QString("function() { a - (b + c); }") << QString("function () { a - (b + c); }");
3956     QTest::newRow("a + -(b + c)") << QString("function() { a + -(b + c); }") << QString("function () { a + -(b + c); }");
3957     QTest::newRow("a + ~(b + c)") << QString("function() { a + ~(b + c); }") << QString("function () { a + ~(b + c); }");
3958     QTest::newRow("a + !(b + c)") << QString("function() { a + !(b + c); }") << QString("function () { a + !(b + c); }");
3959     QTest::newRow("a + +(b + c)") << QString("function() { a + +(b + c); }") << QString("function () { a + +(b + c); }");
3960     QTest::newRow("a + b * c") << QString("function() { a + b * c; }") << QString("function () { a + b * c; }");
3961     QTest::newRow("(a + b) * c") << QString("function() { (a + b) * c; }") << QString("function () { (a + b) * c; }");
3962     QTest::newRow("(a + b) * (c + d)") << QString("function() { (a + b) * (c + d); }") << QString("function () { (a + b) * (c + d); }");
3963     QTest::newRow("a + (b * c)") << QString("function() { a + (b * c); }") << QString("function () { a + (b * c); }");
3964     QTest::newRow("a + (b / c)") << QString("function() { a + (b / c); }") << QString("function () { a + (b / c); }");
3965     QTest::newRow("(a / b) * c") << QString("function() { (a / b) * c; }") << QString("function () { (a / b) * c; }");
3966     QTest::newRow("a / (b * c)") << QString("function() { a / (b * c); }") << QString("function () { a / (b * c); }");
3967     QTest::newRow("a / (b % c)") << QString("function() { a / (b % c); }") << QString("function () { a / (b % c); }");
3968     QTest::newRow("a && b || c") << QString("function() { a && b || c; }") << QString("function () { a && b || c; }");
3969     QTest::newRow("a && (b || c)") << QString("function() { a && (b || c); }") << QString("function () { a && (b || c); }");
3970     QTest::newRow("a & b | c") << QString("function() { a & b | c; }") << QString("function () { a & b | c; }");
3971     QTest::newRow("a & (b | c)") << QString("function() { a & (b | c); }") << QString("function () { a & (b | c); }");
3972     QTest::newRow("a & b | c ^ d") << QString("function() { a & b | c ^ d; }") << QString("function () { a & b | c ^ d; }");
3973     QTest::newRow("a & (b | c ^ d)") << QString("function() { a & (b | c ^ d); }") << QString("function () { a & (b | c ^ d); }");
3974     QTest::newRow("(a & b | c) ^ d") << QString("function() { (a & b | c) ^ d; }") << QString("function () { (a & b | c) ^ d; }");
3975     QTest::newRow("a << b + c") << QString("function() { a << b + c; }") << QString("function () { a << b + c; }");
3976     QTest::newRow("(a << b) + c") << QString("function() { (a << b) + c; }") << QString("function () { (a << b) + c; }");
3977     QTest::newRow("a >> b + c") << QString("function() { a >> b + c; }") << QString("function () { a >> b + c; }");
3978     QTest::newRow("(a >> b) + c") << QString("function() { (a >> b) + c; }") << QString("function () { (a >> b) + c; }");
3979     QTest::newRow("a >>> b + c") << QString("function() { a >>> b + c; }") << QString("function () { a >>> b + c; }");
3980     QTest::newRow("(a >>> b) + c") << QString("function() { (a >>> b) + c; }") << QString("function () { (a >>> b) + c; }");
3981     QTest::newRow("a == b || c != d") << QString("function() { a == b || c != d; }") << QString("function () { a == b || c != d; }");
3982     QTest::newRow("a == (b || c != d)") << QString("function() { a == (b || c != d); }") << QString("function () { a == (b || c != d); }");
3983     QTest::newRow("a === b || c !== d") << QString("function() { a === b || c !== d; }") << QString("function () { a === b || c !== d; }");
3984     QTest::newRow("a === (b || c !== d)") << QString("function() { a === (b || c !== d); }") << QString("function () { a === (b || c !== d); }");
3985     QTest::newRow("a &= b + c") << QString("function() { a &= b + c; }") << QString("function () { a &= b + c; }");
3986     QTest::newRow("debugger") << QString("function() { debugger; }") << QString("function () { debugger; }");
3987 }
3988
3989 void tst_QJSValue::prettyPrinter()
3990 {
3991     QFETCH(QString, function);
3992     QFETCH(QString, expected);
3993     QJSEngine eng;
3994     QJSValue val = eng.evaluate("(" + function + ")");
3995     QVERIFY(val.isCallable());
3996     QString actual = val.toString();
3997     int count = qMin(actual.size(), expected.size());
3998 //    qDebug() << actual << expected;
3999     for (int i = 0; i < count; ++i) {
4000 //        qDebug() << i << actual.at(i) << expected.at(i);
4001         QCOMPARE(actual.at(i), expected.at(i));
4002     }
4003     QCOMPARE(actual.size(), expected.size());
4004 }
4005
4006 void tst_QJSValue::engineDeleted()
4007 {
4008     QJSEngine *eng = new QJSEngine;
4009     QJSValue v1(eng, 123);
4010     QVERIFY(v1.isNumber());
4011     QJSValue v2(eng, QString("ciao"));
4012     QVERIFY(v2.isString());
4013     QJSValue v3 = eng->newObject();
4014     QVERIFY(v3.isObject());
4015     QJSValue v4 = eng->newQObject(this);
4016     QVERIFY(v4.isQObject());
4017     QJSValue v5 = "Hello";
4018     QVERIFY(v2.isString());
4019
4020     delete eng;
4021
4022     QVERIFY(!v1.isValid());
4023     QVERIFY(v1.engine() == 0);
4024     QVERIFY(!v2.isValid());
4025     QVERIFY(v2.engine() == 0);
4026     QVERIFY(!v3.isValid());
4027     QVERIFY(v3.engine() == 0);
4028     QVERIFY(!v4.isValid());
4029     QVERIFY(v4.engine() == 0);
4030     QVERIFY(v5.isValid());
4031     QVERIFY(v5.engine() == 0);
4032
4033     QVERIFY(!v3.property("foo").isValid());
4034 }
4035
4036 void tst_QJSValue::valueOfWithClosure()
4037 {
4038     QJSEngine eng;
4039     // valueOf()
4040     {
4041         QJSValue obj = eng.evaluate("o = {}; (function(foo) { o.valueOf = function() { return foo; } })(123); o");
4042         QVERIFY(obj.isObject());
4043         QCOMPARE(obj.toInt(), 123);
4044     }
4045     // toString()
4046     {
4047         QJSValue obj = eng.evaluate("o = {}; (function(foo) { o.toString = function() { return foo; } })('ciao'); o");
4048         QVERIFY(obj.isObject());
4049         QCOMPARE(obj.toString(), QString::fromLatin1("ciao"));
4050     }
4051 }
4052
4053 #if 0 // FIXME: no objectId()
4054 void tst_QJSValue::objectId()
4055 {
4056     QCOMPARE(QJSValue().objectId(), (qint64)-1);
4057     QCOMPARE(QJSValue(QJSValue::UndefinedValue).objectId(), (qint64)-1);
4058     QCOMPARE(QJSValue(QJSValue::NullValue).objectId(), (qint64)-1);
4059     QCOMPARE(QJSValue(false).objectId(), (qint64)-1);
4060     QCOMPARE(QJSValue(123).objectId(), (qint64)-1);
4061     QCOMPARE(QJSValue(uint(123)).objectId(), (qint64)-1);
4062     QCOMPARE(QJSValue(123.5).objectId(), (qint64)-1);
4063     QCOMPARE(QJSValue("ciao").objectId(), (qint64)-1);
4064
4065     QScriptEngine eng;
4066     QJSValue o1 = eng.newObject();
4067     QVERIFY(o1.objectId() != -1);
4068     QJSValue o2 = eng.newObject();
4069     QVERIFY(o2.objectId() != -1);
4070     QVERIFY(o1.objectId() != o2.objectId());
4071
4072     QVERIFY(eng.objectById(o1.objectId()).strictlyEquals(o1));
4073     QVERIFY(eng.objectById(o2.objectId()).strictlyEquals(o2));
4074
4075     qint64 globalObjectId = -1;
4076     {
4077         QJSValue global = eng.globalObject();
4078         globalObjectId = global.objectId();
4079         QVERIFY(globalObjectId != -1);
4080         QVERIFY(eng.objectById(globalObjectId).strictlyEquals(global));
4081     }
4082     QJSValue obj = eng.objectById(globalObjectId);
4083     QVERIFY(obj.isObject());
4084     QVERIFY(obj.strictlyEquals(eng.globalObject()));
4085 }
4086 #endif
4087
4088 void tst_QJSValue::nestedObjectToVariant_data()
4089 {
4090     QTest::addColumn<QString>("program");
4091     QTest::addColumn<QVariant>("expected");
4092
4093     // Array literals
4094     QTest::newRow("[[]]")
4095         << QString::fromLatin1("[[]]")
4096         << QVariant(QVariantList() << (QVariant(QVariantList())));
4097     QTest::newRow("[[123]]")
4098         << QString::fromLatin1("[[123]]")
4099         << QVariant(QVariantList() << (QVariant(QVariantList() << 123)));
4100     QTest::newRow("[[], 123]")
4101         << QString::fromLatin1("[[], 123]")
4102         << QVariant(QVariantList() << QVariant(QVariantList()) << 123);
4103
4104     // Cyclic arrays
4105     QTest::newRow("var a=[]; a.push(a)")
4106         << QString::fromLatin1("var a=[]; a.push(a); a")
4107         << QVariant(QVariantList() << QVariant(QVariantList()));
4108     QTest::newRow("var a=[]; a.push(123, a)")
4109         << QString::fromLatin1("var a=[]; a.push(123, a); a")
4110         << QVariant(QVariantList() << 123 << QVariant(QVariantList()));
4111     QTest::newRow("var a=[]; var b=[]; a.push(b); b.push(a)")
4112         << QString::fromLatin1("var a=[]; var b=[]; a.push(b); b.push(a); a")
4113         << QVariant(QVariantList() << QVariant(QVariantList() << QVariant(QVariantList())));
4114     QTest::newRow("var a=[]; var b=[]; a.push(123, b); b.push(456, a)")
4115         << QString::fromLatin1("var a=[]; var b=[]; a.push(123, b); b.push(456, a); a")
4116         << QVariant(QVariantList() << 123 << QVariant(QVariantList() << 456 << QVariant(QVariantList())));
4117
4118     // Object literals
4119     {
4120         QVariantMap m;
4121         QTest::newRow("{}")
4122             << QString::fromLatin1("({})")
4123             << QVariant(m);
4124     }
4125     {
4126         QVariantMap m;
4127         m["a"] = QVariantMap();
4128         QTest::newRow("{ a:{} }")
4129             << QString::fromLatin1("({ a:{} })")
4130             << QVariant(m);
4131     }
4132     {
4133         QVariantMap m, m2;
4134         m2["b"] = 10;
4135         m2["c"] = 20;
4136         m["a"] = m2;
4137         QTest::newRow("{ a:{b:10, c:20} }")
4138             << QString::fromLatin1("({ a:{b:10, c:20} })")
4139             << QVariant(m);
4140     }
4141     {
4142         QVariantMap m;
4143         m["a"] = 10;
4144         m["b"] = QVariantList() << 20 << 30;
4145         QTest::newRow("{ a:10, b:[20, 30]}")
4146             << QString::fromLatin1("({ a:10, b:[20,30]})")
4147             << QVariant(m);
4148     }
4149
4150     // Cyclic objects
4151     {
4152         QVariantMap m;
4153         m["p"] = QVariantMap();
4154         QTest::newRow("var o={}; o.p=o")
4155             << QString::fromLatin1("var o={}; o.p=o; o")
4156             << QVariant(m);
4157     }
4158     {
4159         QVariantMap m;
4160         m["p"] = 123;
4161         m["q"] = QVariantMap();
4162         QTest::newRow("var o={}; o.p=123; o.q=o")
4163             << QString::fromLatin1("var o={}; o.p=123; o.q=o; o")
4164             << QVariant(m);
4165     }
4166 }
4167
4168 void tst_QJSValue::nestedObjectToVariant()
4169 {
4170     QJSEngine eng;
4171     QFETCH(QString, program);
4172     QFETCH(QVariant, expected);
4173     QJSValue o = eng.evaluate(program);
4174     QVERIFY(!o.isError());
4175     QVERIFY(o.isObject());
4176     QCOMPARE(o.toVariant(), expected);
4177 }
4178
4179 void tst_QJSValue::propertyFlags_data()
4180 {
4181     QTest::addColumn<QString>("program");
4182     QTest::addColumn<uint>("expected");
4183
4184     QTest::newRow("nothing") << "" << 0u;
4185 #if 0 // FIXME: No getter/setter API
4186     QTest::newRow("getter") << "o.__defineGetter__('prop', function() { return 'blah' } );\n" << uint(QJSValue::PropertyGetter);
4187     QTest::newRow("setter") << "o.__defineSetter__('prop', function(a) { this.setted_prop2 = a; } );\n" << uint(QJSValue::PropertySetter);
4188     QTest::newRow("getterSetter") <<  "o.__defineGetter__('prop', function() { return 'ploup' } );\n"
4189                                       "o.__defineSetter__('prop', function(a) { this.setted_prop3 = a; } );\n" << uint(QJSValue::PropertySetter|QJSValue::PropertyGetter);
4190 #endif
4191     QTest::newRow("nothing2") << "o.prop = 'nothing'" << 0u;
4192 }
4193
4194 void tst_QJSValue::propertyFlags()
4195 {
4196     QFETCH(QString, program);
4197     QFETCH(uint, expected);
4198     QJSEngine eng;
4199     eng.evaluate("o = new Object;");
4200     eng.evaluate(program);
4201     QJSValue o = eng.evaluate("o");
4202
4203     QCOMPARE(uint(o.propertyFlags("prop")), expected);
4204 }
4205
4206
4207 QTEST_MAIN(tst_QJSValue)