initial import
[vuplus_webkit] / Source / JavaScriptCore / qt / tests / qscriptvalue / tst_qscriptvalue.cpp
1 /*
2     Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
3
4     This library is free software; you can redistribute it and/or
5     modify it under the terms of the GNU Library General Public
6     License as published by the Free Software Foundation; either
7     version 2 of the License, or (at your option) any later version.
8
9     This library is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12     Library General Public License for more details.
13
14     You should have received a copy of the GNU Library General Public License
15     along with this library; see the file COPYING.LIB.  If not, write to
16     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17     Boston, MA 02110-1301, USA.
18 */
19
20 #include "tst_qscriptvalue.h"
21 #include <QtCore/qnumeric.h>
22
23 tst_QScriptValue::tst_QScriptValue()
24     : m_engine(0)
25 {
26 }
27
28 tst_QScriptValue::~tst_QScriptValue()
29 {
30     delete m_engine;
31 }
32
33 void tst_QScriptValue::ctor()
34 {
35     QScriptEngine eng;
36     {
37         QScriptValue v;
38         QCOMPARE(v.isValid(), false);
39         QCOMPARE(v.engine(), (QScriptEngine*)0);
40     }
41     {
42         QScriptValue v(&eng, QScriptValue::UndefinedValue);
43         QCOMPARE(v.isValid(), true);
44         QCOMPARE(v.isUndefined(), true);
45         QCOMPARE(v.isObject(), false);
46         QCOMPARE(v.engine(), &eng);
47     }
48     {
49         QScriptValue v(&eng, QScriptValue::NullValue);
50         QCOMPARE(v.isValid(), true);
51         QCOMPARE(v.isNull(), true);
52         QCOMPARE(v.isObject(), false);
53         QCOMPARE(v.engine(), &eng);
54     }
55     {
56         QScriptValue v(&eng, false);
57         QCOMPARE(v.isValid(), true);
58         QCOMPARE(v.isBoolean(), true);
59         QCOMPARE(v.isBool(), true);
60         QCOMPARE(v.isObject(), false);
61         QCOMPARE(v.toBoolean(), false);
62         QCOMPARE(v.engine(), &eng);
63     }
64     {
65         QScriptValue v(&eng, int(1));
66         QCOMPARE(v.isValid(), true);
67         QCOMPARE(v.isNumber(), true);
68         QCOMPARE(v.isObject(), false);
69         QCOMPARE(v.toNumber(), 1.0);
70         QCOMPARE(v.engine(), &eng);
71     }
72     {
73         QScriptValue v(int(0x43211234));
74         QVERIFY(v.isNumber());
75         QCOMPARE(v.toInt32(), 0x43211234);
76     }
77     {
78         QScriptValue v(&eng, uint(1));
79         QCOMPARE(v.isValid(), true);
80         QCOMPARE(v.isNumber(), true);
81         QCOMPARE(v.isObject(), false);
82         QCOMPARE(v.toNumber(), 1.0);
83         QCOMPARE(v.engine(), &eng);
84     }
85     {
86         QScriptValue v(uint(0x43211234));
87         QVERIFY(v.isNumber());
88         QCOMPARE(v.toUInt32(), uint(0x43211234));
89     }
90     {
91         QScriptValue v(&eng, 1.0);
92         QCOMPARE(v.isValid(), true);
93         QCOMPARE(v.isNumber(), true);
94         QCOMPARE(v.isObject(), false);
95         QCOMPARE(v.toNumber(), 1.0);
96         QCOMPARE(v.engine(), &eng);
97     }
98     {
99         QScriptValue v(12345678910.5);
100         QVERIFY(v.isNumber());
101         QCOMPARE(v.toNumber(), 12345678910.5);
102     }
103     {
104         QScriptValue v(&eng, "ciao");
105         QCOMPARE(v.isValid(), true);
106         QCOMPARE(v.isString(), true);
107         QCOMPARE(v.isObject(), false);
108         QCOMPARE(v.toString(), QLatin1String("ciao"));
109         QCOMPARE(v.engine(), &eng);
110     }
111     {
112         QScriptValue v(&eng, QString("ciao"));
113         QCOMPARE(v.isValid(), true);
114         QCOMPARE(v.isString(), true);
115         QCOMPARE(v.isObject(), false);
116         QCOMPARE(v.toString(), QLatin1String("ciao"));
117         QCOMPARE(v.engine(), &eng);
118     }
119     // copy constructor, operator=
120     {
121         QScriptValue v(&eng, 1.0);
122         QScriptValue v2(v);
123         QCOMPARE(v2.strictlyEquals(v), true);
124         QCOMPARE(v2.engine(), &eng);
125
126         QScriptValue v3(v);
127         QCOMPARE(v3.strictlyEquals(v), true);
128         QCOMPARE(v3.strictlyEquals(v2), true);
129         QCOMPARE(v3.engine(), &eng);
130
131         QScriptValue v4(&eng, 2.0);
132         QCOMPARE(v4.strictlyEquals(v), false);
133         v3 = v4;
134         QCOMPARE(v3.strictlyEquals(v), false);
135         QCOMPARE(v3.strictlyEquals(v4), true);
136
137         v2 = QScriptValue();
138         QCOMPARE(v2.strictlyEquals(v), false);
139         QCOMPARE(v.toNumber(), 1.0);
140
141         QScriptValue v5(v);
142         QCOMPARE(v5.strictlyEquals(v), true);
143         v = QScriptValue();
144         QCOMPARE(v5.strictlyEquals(v), false);
145         QCOMPARE(v5.toNumber(), 1.0);
146     }
147
148     // constructors that take no engine argument
149     {
150         QScriptValue v(QScriptValue::UndefinedValue);
151         QCOMPARE(v.isValid(), true);
152         QCOMPARE(v.isUndefined(), true);
153         QCOMPARE(v.isObject(), false);
154         QCOMPARE(v.engine(), (QScriptEngine*)0);
155     }
156     {
157         QScriptValue v(QScriptValue::NullValue);
158         QCOMPARE(v.isValid(), true);
159         QCOMPARE(v.isNull(), true);
160         QCOMPARE(v.isObject(), false);
161         QCOMPARE(v.engine(), (QScriptEngine*)0);
162     }
163     {
164         QScriptValue v(false);
165         QCOMPARE(v.isValid(), true);
166         QCOMPARE(v.isBoolean(), true);
167         QCOMPARE(v.isBool(), true);
168         QCOMPARE(v.isObject(), false);
169         QCOMPARE(v.toBoolean(), false);
170         QCOMPARE(v.engine(), (QScriptEngine*)0);
171     }
172     {
173         QScriptValue v(int(1));
174         QCOMPARE(v.isValid(), true);
175         QCOMPARE(v.isNumber(), true);
176         QCOMPARE(v.isObject(), false);
177         QCOMPARE(v.toNumber(), 1.0);
178         QCOMPARE(v.engine(), (QScriptEngine*)0);
179     }
180     {
181         QScriptValue v(uint(1));
182         QCOMPARE(v.isValid(), true);
183         QCOMPARE(v.isNumber(), true);
184         QCOMPARE(v.isObject(), false);
185         QCOMPARE(v.toNumber(), 1.0);
186         QCOMPARE(v.engine(), (QScriptEngine*)0);
187     }
188     {
189         QScriptValue 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(), (QScriptEngine*)0);
195     }
196     {
197         QScriptValue v("ciao");
198         QCOMPARE(v.isValid(), true);
199         QCOMPARE(v.isString(), true);
200         QCOMPARE(v.isObject(), false);
201         QCOMPARE(v.toString(), QLatin1String("ciao"));
202         QCOMPARE(v.engine(), (QScriptEngine*)0);
203     }
204     {
205         QScriptValue v(QString("ciao"));
206         QCOMPARE(v.isValid(), true);
207         QCOMPARE(v.isString(), true);
208         QCOMPARE(v.isObject(), false);
209         QCOMPARE(v.toString(), QLatin1String("ciao"));
210         QCOMPARE(v.engine(), (QScriptEngine*)0);
211     }
212     // copy constructor, operator=
213     {
214         QScriptValue v(1.0);
215         QScriptValue v2(v);
216         QCOMPARE(v2.strictlyEquals(v), true);
217         QCOMPARE(v2.engine(), (QScriptEngine*)0);
218
219         QScriptValue v3(v);
220         QCOMPARE(v3.strictlyEquals(v), true);
221         QCOMPARE(v3.strictlyEquals(v2), true);
222         QCOMPARE(v3.engine(), (QScriptEngine*)0);
223
224         QScriptValue v4(2.0);
225         QCOMPARE(v4.strictlyEquals(v), false);
226         v3 = v4;
227         QCOMPARE(v3.strictlyEquals(v), false);
228         QCOMPARE(v3.strictlyEquals(v4), true);
229
230         v2 = QScriptValue();
231         QCOMPARE(v2.strictlyEquals(v), false);
232         QCOMPARE(v.toNumber(), 1.0);
233
234         QScriptValue v5(v);
235         QCOMPARE(v5.strictlyEquals(v), true);
236         v = QScriptValue();
237         QCOMPARE(v5.strictlyEquals(v), false);
238         QCOMPARE(v5.toNumber(), 1.0);
239     }
240
241     // 0 engine
242     QVERIFY(QScriptValue(0, QScriptValue::UndefinedValue).isUndefined());
243     QVERIFY(QScriptValue(0, QScriptValue::NullValue).isNull());
244     QVERIFY(QScriptValue(0, false).isBool());
245     QVERIFY(QScriptValue(0, int(1)).isNumber());
246     QVERIFY(QScriptValue(0, uint(1)).isNumber());
247     QVERIFY(QScriptValue(0, 1.0).isNumber());
248     QVERIFY(QScriptValue(0, "ciao").isString());
249     QVERIFY(QScriptValue(0, QString("ciao")).isString());
250 }
251
252 void tst_QScriptValue::getPropertySimple_data()
253 {
254     QTest::addColumn<QString>("code");
255     QTest::addColumn<QString>("propertyName");
256     QTest::addColumn<QString>("desc");
257     QTest::addColumn<bool>("isArrayIndex");
258
259     QTest::newRow("new Array()")
260             << QString::fromAscii("new Array()")
261             << QString::fromAscii("length")
262             << QString::fromAscii("0")
263             << false;
264     QTest::newRow("new Object().length")
265             << QString::fromAscii("new Object()")
266             << QString::fromAscii("length")
267             << QString::fromAscii("") // Undefined is an invalid property.
268             << false;
269     QTest::newRow("new Object().toString")
270             << QString::fromAscii("new Object()")
271             << QString::fromAscii("toString")
272             << QString::fromAscii("function toString() {\n    [native code]\n}")
273             << false;
274     QTest::newRow("[1,2,3,4]")
275             << QString::fromAscii("[1,2,3,'s',4]")
276             << QString::fromAscii("2")
277             << QString::fromAscii("3")
278             << true;
279     QTest::newRow("[1,3,'a','b']")
280             << QString::fromAscii("[1,3,'a','b']")
281             << QString::fromAscii("3")
282             << QString::fromAscii("b")
283             << true;
284     QTest::newRow("[4,5]")
285             << QString::fromAscii("[4,5]")
286             << QString::fromAscii("123")
287             << QString::fromAscii("") // Undefined is an invalid property.
288             << true;
289     QTest::newRow("[1,3,4]")
290             << QString::fromAscii("[1,3,4]")
291             << QString::fromAscii("abc")
292             << QString::fromAscii("") // Undefined is an invalid property.
293             << true;
294 }
295
296 void tst_QScriptValue::getPropertySimple()
297 {
298     QFETCH(QString, code);
299     QFETCH(QString, propertyName);
300     QFETCH(QString, desc);
301
302     QScriptEngine engine;
303     QScriptValue object = engine.evaluate(code);
304     QVERIFY(object.isValid());
305     {
306         QScriptValue property = object.property(propertyName);
307         QCOMPARE(property.toString(), desc);
308     }
309     {
310         QScriptString name = engine.toStringHandle(propertyName);
311         QScriptValue property = object.property(name);
312         QCOMPARE(property.toString(), desc);
313     }
314     {
315         bool ok;
316         quint32 idx = engine.toStringHandle(propertyName).toArrayIndex(&ok);
317         if (ok) {
318             QScriptValue property = object.property(idx);
319             QCOMPARE(property.toString(), desc);
320         }
321     }
322 }
323
324 void tst_QScriptValue::setPropertySimple()
325 {
326     QScriptEngine engine;
327     {
328         QScriptValue invalid;
329         QScriptValue property(1234);
330
331         invalid.setProperty("aaa", property);
332         invalid.setProperty(13, property);
333         invalid.setProperty(engine.toStringHandle("aaa"), property);
334
335         QVERIFY(!invalid.property("aaa").isValid());
336         QVERIFY(!invalid.property(13).isValid());
337         QVERIFY(!invalid.property(engine.toStringHandle("aaa")).isValid());
338     }
339     {
340         QScriptValue object = engine.newObject();
341         QScriptValue property;
342
343         object.setProperty(13, property);
344         object.setProperty("aaa", property);
345         object.setProperty(engine.toStringHandle("aaa"), property);
346
347         QVERIFY(!object.property(13).isValid());
348         QVERIFY(!object.property("aaa").isValid());
349         QVERIFY(!object.property(engine.toStringHandle("aaa")).isValid());
350     }
351     {
352         // Check if setting an invalid property works as deleteProperty.
353         QScriptValue object = engine.evaluate("o = {13: 0, 'aaa': 3, 'bbb': 1}");
354         QScriptValue property;
355
356         QVERIFY(object.property(13).isValid());
357         QVERIFY(object.property("aaa").isValid());
358         QVERIFY(object.property(engine.toStringHandle("aaa")).isValid());
359
360         object.setProperty(13, property);
361         object.setProperty("aaa", property);
362         object.setProperty(engine.toStringHandle("bbb"), property);
363
364         QVERIFY(!object.property(13).isValid());
365         QVERIFY(!object.property("aaa").isValid());
366         QVERIFY(!object.property(engine.toStringHandle("aaa")).isValid());
367     }
368     {
369         QScriptValue object = engine.evaluate("new Object");
370         QVERIFY(object.isObject());
371         QScriptValue property = object.property("foo");
372         QVERIFY(!property.isValid());
373         property = QScriptValue(2);
374         object.setProperty("foo", property);
375         QVERIFY(object.property("foo").isNumber());
376         QVERIFY(object.property("foo").toNumber() == 2);
377     }
378     {
379         QScriptValue o1 = engine.evaluate("o1 = new Object; o1");
380         QScriptValue o2 = engine.evaluate("o2 = new Object; o2");
381         QVERIFY(engine.evaluate("o1.__proto__ = o2; o1.__proto__ === o2").toBool());
382         QVERIFY(engine.evaluate("o2.foo = 22; o1.foo == 22").toBool());
383         QVERIFY(o1.property("foo").toString() == "22");
384         o2.setProperty("foo", QScriptValue(&engine, 456.0));
385         QVERIFY(engine.evaluate("o1.foo == 456").toBool());
386         QVERIFY(o1.property("foo").isNumber());
387     }
388 }
389
390 void tst_QScriptValue::getPropertyResolveFlag()
391 {
392     QScriptEngine engine;
393     QScriptValue object1 = engine.evaluate("o1 = new Object();");
394     QScriptValue object2 = engine.evaluate("o2 = new Object(); o1.__proto__ = o2; o2");
395     QScriptValue number(&engine, 456.0);
396     QVERIFY(object1.isObject());
397     QVERIFY(object2.isObject());
398     QVERIFY(number.isNumber());
399
400     object2.setProperty("propertyInPrototype", number);
401     QVERIFY(object2.property("propertyInPrototype").isNumber());
402     // default is ResolvePrototype
403     QCOMPARE(object1.property("propertyInPrototype").strictlyEquals(number), true);
404     QCOMPARE(object1.property("propertyInPrototype", QScriptValue::ResolvePrototype)
405              .strictlyEquals(number), true);
406     QCOMPARE(object1.property("propertyInPrototype", QScriptValue::ResolveLocal).isValid(), false);
407 }
408
409 void tst_QScriptValue::getSetProperty()
410 {
411     QScriptEngine eng;
412
413     QScriptValue object = eng.newObject();
414
415     QScriptValue str = QScriptValue(&eng, "bar");
416     object.setProperty("foo", str);
417     QCOMPARE(object.property("foo").toString(), str.toString());
418
419     QScriptValue num = QScriptValue(&eng, 123.0);
420     object.setProperty("baz", num);
421     QCOMPARE(object.property("baz").toNumber(), num.toNumber());
422
423     QScriptValue strstr = QScriptValue("bar");
424     QCOMPARE(strstr.engine(), (QScriptEngine *)0);
425     object.setProperty("foo", strstr);
426     QCOMPARE(object.property("foo").toString(), strstr.toString());
427     QCOMPARE(strstr.engine(), &eng); // the value has been bound to the engine
428
429     QScriptValue numnum = QScriptValue(123.0);
430     object.setProperty("baz", numnum);
431     QCOMPARE(object.property("baz").toNumber(), numnum.toNumber());
432
433     QScriptValue inv;
434     inv.setProperty("foo", num);
435     QCOMPARE(inv.property("foo").isValid(), false);
436
437     QScriptValue array = eng.newArray();
438     array.setProperty(0, num);
439     QCOMPARE(array.property(0).toNumber(), num.toNumber());
440     QCOMPARE(array.property("0").toNumber(), num.toNumber());
441     QCOMPARE(array.property("length").toUInt32(), quint32(1));
442     array.setProperty(1, str);
443     QCOMPARE(array.property(1).toString(), str.toString());
444     QCOMPARE(array.property("1").toString(), str.toString());
445     QCOMPARE(array.property("length").toUInt32(), quint32(2));
446     array.setProperty("length", QScriptValue(&eng, 1));
447     QCOMPARE(array.property("length").toUInt32(), quint32(1));
448     QCOMPARE(array.property(1).isValid(), false);
449
450     // task 162051 -- detecting whether the property is an array index or not
451     QVERIFY(eng.evaluate("a = []; a['00'] = 123; a['00']").strictlyEquals(QScriptValue(&eng, 123)));
452     QVERIFY(eng.evaluate("a.length").strictlyEquals(QScriptValue(&eng, 0)));
453     QVERIFY(eng.evaluate("a.hasOwnProperty('00')").strictlyEquals(QScriptValue(&eng, true)));
454     QVERIFY(eng.evaluate("a.hasOwnProperty('0')").strictlyEquals(QScriptValue(&eng, false)));
455     QVERIFY(eng.evaluate("a[0]").isUndefined());
456     QVERIFY(eng.evaluate("a[0.5] = 456; a[0.5]").strictlyEquals(QScriptValue(&eng, 456)));
457     QVERIFY(eng.evaluate("a.length").strictlyEquals(QScriptValue(&eng, 0)));
458     QVERIFY(eng.evaluate("a.hasOwnProperty('0.5')").strictlyEquals(QScriptValue(&eng, true)));
459     QVERIFY(eng.evaluate("a[0]").isUndefined());
460     QVERIFY(eng.evaluate("a[0] = 789; a[0]").strictlyEquals(QScriptValue(&eng, 789)));
461     QVERIFY(eng.evaluate("a.length").strictlyEquals(QScriptValue(&eng, 1)));
462
463     // task 183072 -- 0x800000000 is not an array index
464     eng.evaluate("a = []; a[0x800000000] = 123");
465     QVERIFY(eng.evaluate("a.length").strictlyEquals(QScriptValue(&eng, 0)));
466     QVERIFY(eng.evaluate("a[0]").isUndefined());
467     QVERIFY(eng.evaluate("a[0x800000000]").strictlyEquals(QScriptValue(&eng, 123)));
468
469     QScriptEngine otherEngine;
470     QScriptValue otherNum = QScriptValue(&otherEngine, 123);
471     QTest::ignoreMessage(QtWarningMsg, "QScriptValue::setProperty() failed: cannot set value created in a different engine");
472     object.setProperty("oof", otherNum);
473     QCOMPARE(object.property("oof").isValid(), false);
474
475     // test ResolveMode
476     QScriptValue object2 = eng.newObject();
477     object.setPrototype(object2);
478     QScriptValue num2 = QScriptValue(&eng, 456.0);
479     object2.setProperty("propertyInPrototype", num2);
480     // default is ResolvePrototype
481     QCOMPARE(object.property("propertyInPrototype")
482              .strictlyEquals(num2), true);
483     QCOMPARE(object.property("propertyInPrototype", QScriptValue::ResolvePrototype)
484              .strictlyEquals(num2), true);
485     QCOMPARE(object.property("propertyInPrototype", QScriptValue::ResolveLocal)
486              .isValid(), false);
487     QEXPECT_FAIL("", "QScriptValue::ResolveScope is not implemented", Continue);
488     QCOMPARE(object.property("propertyInPrototype", QScriptValue::ResolveScope)
489              .strictlyEquals(num2), false);
490     QCOMPARE(object.property("propertyInPrototype", QScriptValue::ResolveFull)
491              .strictlyEquals(num2), true);
492
493     // test property removal (setProperty(QScriptValue()))
494     QScriptValue object3 = eng.newObject();
495     object3.setProperty("foo", num);
496     QCOMPARE(object3.property("foo").strictlyEquals(num), true);
497     object3.setProperty("bar", str);
498     QCOMPARE(object3.property("bar").strictlyEquals(str), true);
499     object3.setProperty("foo", QScriptValue());
500     QCOMPARE(object3.property("foo").isValid(), false);
501     QCOMPARE(object3.property("bar").strictlyEquals(str), true);
502     object3.setProperty("foo", num);
503     QCOMPARE(object3.property("foo").strictlyEquals(num), true);
504     QCOMPARE(object3.property("bar").strictlyEquals(str), true);
505     object3.setProperty("bar", QScriptValue());
506     QCOMPARE(object3.property("bar").isValid(), false);
507     QCOMPARE(object3.property("foo").strictlyEquals(num), true);
508     object3.setProperty("foo", QScriptValue());
509     object3.setProperty("foo", QScriptValue());
510
511     eng.globalObject().setProperty("object3", object3);
512     QCOMPARE(eng.evaluate("object3.hasOwnProperty('foo')")
513              .strictlyEquals(QScriptValue(&eng, false)), true);
514     object3.setProperty("foo", num);
515     QCOMPARE(eng.evaluate("object3.hasOwnProperty('foo')")
516              .strictlyEquals(QScriptValue(&eng, true)), true);
517     eng.globalObject().setProperty("object3", QScriptValue());
518     QCOMPARE(eng.evaluate("this.hasOwnProperty('object3')")
519              .strictlyEquals(QScriptValue(&eng, false)), true);
520
521     eng.globalObject().setProperty("object", object);
522
523     // ReadOnly
524     object.setProperty("readOnlyProperty", num, QScriptValue::ReadOnly);
525     // QCOMPARE(object.propertyFlags("readOnlyProperty"), QScriptValue::ReadOnly);
526     QCOMPARE(object.property("readOnlyProperty").strictlyEquals(num), true);
527     eng.evaluate("object.readOnlyProperty = !object.readOnlyProperty");
528     QCOMPARE(object.property("readOnlyProperty").strictlyEquals(num), true);
529     // Should still be part of enumeration.
530     {
531         QScriptValue ret = eng.evaluate(
532             "found = false;"
533             "for (var p in object) {"
534             "  if (p == 'readOnlyProperty') {"
535             "    found = true; break;"
536             "  }"
537             "} found");
538         QCOMPARE(ret.strictlyEquals(QScriptValue(&eng, true)), true);
539     }
540     // should still be deletable
541     {
542         QScriptValue ret = eng.evaluate("delete object.readOnlyProperty");
543         QCOMPARE(ret.strictlyEquals(QScriptValue(&eng, true)), true);
544         QCOMPARE(object.property("readOnlyProperty").isValid(), false);
545     }
546
547     // Undeletable
548     object.setProperty("undeletableProperty", num, QScriptValue::Undeletable);
549     // QCOMPARE(object.propertyFlags("undeletableProperty"), QScriptValue::Undeletable);
550     QCOMPARE(object.property("undeletableProperty").strictlyEquals(num), true);
551     {
552         QScriptValue ret = eng.evaluate("delete object.undeletableProperty");
553         QCOMPARE(ret.strictlyEquals(QScriptValue(&eng, true)), false);
554         QCOMPARE(object.property("undeletableProperty").strictlyEquals(num), true);
555     }
556     // should still be writable
557     eng.evaluate("object.undeletableProperty = object.undeletableProperty + 1");
558     QCOMPARE(object.property("undeletableProperty").toNumber(), num.toNumber() + 1);
559     // should still be part of enumeration
560     {
561         QScriptValue ret = eng.evaluate(
562             "found = false;"
563             "for (var p in object) {"
564             "  if (p == 'undeletableProperty') {"
565             "    found = true; break;"
566             "  }"
567             "} found");
568         QCOMPARE(ret.strictlyEquals(QScriptValue(&eng, true)), true);
569     }
570     // should still be deletable from C++
571     object.setProperty("undeletableProperty", QScriptValue());
572     QEXPECT_FAIL("", "With JSC-based back-end, undeletable properties can't be deleted from C++", Continue);
573     QVERIFY(!object.property("undeletableProperty").isValid());
574     // QEXPECT_FAIL("", "With JSC-based back-end, undeletable properties can't be deleted from C++", Continue);
575     // QCOMPARE(object.propertyFlags("undeletableProperty"), 0);
576
577     // SkipInEnumeration
578     object.setProperty("dontEnumProperty", num, QScriptValue::SkipInEnumeration);
579     // QCOMPARE(object.propertyFlags("dontEnumProperty"), QScriptValue::SkipInEnumeration);
580     QCOMPARE(object.property("dontEnumProperty").strictlyEquals(num), true);
581     // should not be part of enumeration
582     {
583         QScriptValue ret = eng.evaluate(
584             "found = false;"
585             "for (var p in object) {"
586             "  if (p == 'dontEnumProperty') {"
587             "    found = true; break;"
588             "  }"
589             "} found");
590         QCOMPARE(ret.strictlyEquals(QScriptValue(&eng, false)), true);
591     }
592     // should still be writable
593     eng.evaluate("object.dontEnumProperty = object.dontEnumProperty + 1");
594     QCOMPARE(object.property("dontEnumProperty").toNumber(), num.toNumber() + 1);
595     // should still be deletable
596     {
597         QScriptValue ret = eng.evaluate("delete object.dontEnumProperty");
598         QCOMPARE(ret.strictlyEquals(QScriptValue(&eng, true)), true);
599         QCOMPARE(object.property("dontEnumProperty").isValid(), false);
600     }
601
602     // change flags
603     object.setProperty("flagProperty", str);
604     // QCOMPARE(object.propertyFlags("flagProperty"), static_cast<QScriptValue::PropertyFlags>(0));
605
606     object.setProperty("flagProperty", str, QScriptValue::ReadOnly);
607     // QCOMPARE(object.propertyFlags("flagProperty"), QScriptValue::ReadOnly);
608
609     // object.setProperty("flagProperty", str, object.propertyFlags("flagProperty") | QScriptValue::SkipInEnumeration);
610     // QCOMPARE(object.propertyFlags("flagProperty"), QScriptValue::ReadOnly | QScriptValue::SkipInEnumeration);
611
612     object.setProperty("flagProperty", str, QScriptValue::KeepExistingFlags);
613     // QCOMPARE(object.propertyFlags("flagProperty"), QScriptValue::ReadOnly | QScriptValue::SkipInEnumeration);
614
615     object.setProperty("flagProperty", str, QScriptValue::UserRange);
616     // QCOMPARE(object.propertyFlags("flagProperty"), QScriptValue::UserRange);
617
618     // flags of property in the prototype
619     {
620         QScriptValue object2 = eng.newObject();
621         object2.setPrototype(object);
622         // QCOMPARE(object2.propertyFlags("flagProperty", QScriptValue::ResolveLocal), 0);
623         // QCOMPARE(object2.propertyFlags("flagProperty"), QScriptValue::UserRange);
624     }
625
626     // using interned strings
627     QScriptString foo = eng.toStringHandle("foo");
628
629     object.setProperty(foo, QScriptValue());
630     QVERIFY(!object.property(foo).isValid());
631
632     object.setProperty(foo, num);
633     QVERIFY(object.property(foo).strictlyEquals(num));
634     QVERIFY(object.property("foo").strictlyEquals(num));
635     // QVERIFY(object.propertyFlags(foo) == 0);
636 }
637
638 void tst_QScriptValue::toStringSimple_data()
639 {
640     QTest::addColumn<QString>("code");
641     QTest::addColumn<QString>("result");
642
643     QTest::newRow("string") << QString::fromAscii("'hello'") << QString::fromAscii("hello");
644     QTest::newRow("string utf") << QString::fromUtf8("'ąśćżźółńę'") << QString::fromUtf8("ąśćżźółńę");
645     QTest::newRow("expression") << QString::fromAscii("1 + 4") << QString::fromAscii("5");
646     QTest::newRow("null") << QString::fromAscii("null") << QString::fromAscii("null");
647     QTest::newRow("boolean") << QString::fromAscii("false") << QString::fromAscii("false");
648     QTest::newRow("undefined") << QString::fromAscii("undefined") << QString::fromAscii("undefined");
649     QTest::newRow("object") << QString::fromAscii("new Object") << QString::fromAscii("[object Object]");
650 }
651
652 /* Test conversion to string from different JSC types */
653 void tst_QScriptValue::toStringSimple()
654 {
655     QFETCH(QString, code);
656     QFETCH(QString, result);
657
658     QScriptEngine engine;
659     QCOMPARE(engine.evaluate(code).toString(), result);
660 }
661
662 void tst_QScriptValue::copyConstructor_data()
663 {
664     QScriptEngine engine;
665     QScriptValue nnumber(123);
666     QScriptValue nstring("ping");
667     QScriptValue number(engine.evaluate("1"));
668     QScriptValue string(engine.evaluate("'foo'"));
669     QScriptValue object(engine.evaluate("new Object"));
670     QScriptValue undefined(engine.evaluate("undefined"));
671     QScriptValue null(engine.evaluate("null"));
672
673     QTest::addColumn<QScriptValue>("value");
674     QTest::addColumn<QString>("result");
675
676     QTest::newRow("native number") << nnumber << QString::number(123);
677     QTest::newRow("native string") << nstring << QString("ping");
678     QTest::newRow("number") << number << QString::fromAscii("1");
679     QTest::newRow("string") << string << QString::fromAscii("foo");
680     QTest::newRow("object") << object << QString::fromAscii("[object Object]");
681     QTest::newRow("undefined") << undefined << QString::fromAscii("undefined");
682     QTest::newRow("null") << null << QString::fromAscii("null");
683 }
684
685 void tst_QScriptValue::copyConstructor()
686 {
687     QFETCH(QScriptValue, value);
688     QFETCH(QString, result);
689
690     QVERIFY(value.isValid());
691     QScriptValue tmp(value);
692     QVERIFY(tmp.isValid());
693     QCOMPARE(tmp.toString(), result);
694 }
695
696 void tst_QScriptValue::assignOperator_data()
697 {
698     copyConstructor_data();
699 }
700
701 void tst_QScriptValue::assignOperator()
702 {
703     QFETCH(QScriptValue, value);
704     QFETCH(QString, result);
705
706     QScriptValue tmp;
707     tmp = value;
708     QVERIFY(tmp.isValid());
709     QCOMPARE(tmp.toString(), result);
710 }
711
712 /* Test internal data sharing between a diffrenet QScriptValue. */
713 void tst_QScriptValue::dataSharing()
714 {
715     QScriptEngine engine;
716     QScriptValue v1;
717     QScriptValue v2(v1);
718
719     v1 = engine.evaluate("1"); // v1 == 1 ; v2 invalid.
720     QVERIFY(v1.isValid());
721     QVERIFY(!v2.isValid());
722
723     v2 = v1; // v1 == 1; v2 == 1.
724     QVERIFY(v1.isValid());
725     QVERIFY(v2.isValid());
726
727     v1 = engine.evaluate("obj = new Date"); // v1 == [object Date] ; v2 == 1.
728     QVERIFY(v1.isValid());
729     QVERIFY(v2.isValid());
730     QVERIFY(v2.toString() != v1.toString());
731
732     // TODO add object manipulation (v1 and v2 point to the same object).
733 }
734
735 void tst_QScriptValue::constructors_data()
736 {
737     QScriptEngine engine;
738
739     QTest::addColumn<QScriptValue>("value");
740     QTest::addColumn<QString>("string");
741     QTest::addColumn<bool>("valid");
742     QTest::addColumn<bool>("object");
743
744     QTest::newRow("invalid") << QScriptValue() << QString() << false << false;
745     QTest::newRow("number") << QScriptValue(-21) << QString::number(-21) << true << false;
746     QTest::newRow("bool") << QScriptValue(true) << QString::fromAscii("true") << true << false;
747     QTest::newRow("double") << QScriptValue(21.12) << QString::number(21.12) << true << false;
748     QTest::newRow("string") << QScriptValue("AlaMaKota") << QString::fromAscii("AlaMaKota") << true << false;
749     QTest::newRow("object") << engine.evaluate("new Object") << QString::fromAscii("[object Object]") << true << true;
750     QTest::newRow("null") << QScriptValue(QScriptValue::NullValue)<< QString::fromAscii("null") << true << false;
751     QTest::newRow("undef") << QScriptValue(QScriptValue::UndefinedValue)<< QString::fromAscii("undefined") << true << false;
752 }
753
754 void tst_QScriptValue::constructors()
755 {
756     QFETCH(QScriptValue, value);
757     QFETCH(QString, string);
758     QFETCH(bool, valid);
759     QFETCH(bool, object);
760
761     QCOMPARE(value.isValid(), valid);
762     QCOMPARE(value.toString(), string);
763     QCOMPARE(value.isObject(), object);
764 }
765
766 void tst_QScriptValue::call()
767 {
768     QScriptEngine engine;
769     QScriptValue ping = engine.evaluate("( function() {return 'ping';} )");
770     QScriptValue incr = engine.evaluate("( function(i) {return i + 1;} )");
771     QScriptValue one(1);
772     QScriptValue five(5);
773     QScriptValue result;
774
775     QVERIFY(one.isValid());
776     QVERIFY(five.isValid());
777
778     QVERIFY(ping.isValid());
779     QVERIFY(ping.isFunction());
780     result = ping.call();
781     QVERIFY(result.isValid());
782     QCOMPARE(result.toString(), QString::fromUtf8("ping"));
783
784     QVERIFY(incr.isValid());
785     QVERIFY(incr.isFunction());
786     result = incr.call(QScriptValue(), QScriptValueList() << one);
787     QVERIFY(result.isValid());
788     QCOMPARE(result.toString(), QString("2"));
789
790     QCOMPARE(incr.call(QScriptValue(), QScriptValueList() << five).toString(), QString::fromAscii("6"));
791
792     QVERIFY(incr.call().isValid()); // Exception.
793 }
794
795 void tst_QScriptValue::getSetPrototype()
796 {
797     QScriptEngine engine;
798     QScriptValue object = engine.evaluate("new Object()");
799     QScriptValue object2 = engine.evaluate("new Object()");
800     object2.setPrototype(object);
801     QCOMPARE(object2.prototype().strictlyEquals(object), true);
802
803     QScriptValue inv;
804     inv.setPrototype(object);
805     QCOMPARE(inv.prototype().isValid(), false);
806
807     QScriptEngine otherEngine;
808     QScriptValue object3 = otherEngine.evaluate("new Object()");
809     QTest::ignoreMessage(QtWarningMsg, "QScriptValue::setPrototype() failed: cannot set a prototype created in a different engine");
810     object2.setPrototype(object3);
811     QCOMPARE(object2.prototype().strictlyEquals(object), true);
812
813     // cyclic prototypes
814     {
815         QScriptValue ret = engine.evaluate("o = { }; p = { }; o.__proto__ = p; p.__proto__ = o");
816         QCOMPARE(ret.isError(), true);
817         QCOMPARE(ret.toString(), QLatin1String("Error: cyclic __proto__ value"));
818     }
819     {
820         QScriptValue ret = engine.evaluate("p.__proto__ = { }");
821         QCOMPARE(ret.isError(), false);
822     }
823
824     QScriptValue old = object.prototype();
825     QTest::ignoreMessage(QtWarningMsg, "QScriptValue::setPrototype() failed: cyclic prototype value");
826     object.setPrototype(object);
827     QCOMPARE(object.prototype().strictlyEquals(old), true);
828
829     object2.setPrototype(object);
830     QTest::ignoreMessage(QtWarningMsg, "QScriptValue::setPrototype() failed: cyclic prototype value");
831     object.setPrototype(object2);
832     QCOMPARE(object.prototype().strictlyEquals(old), true);
833 }
834
835 void tst_QScriptValue::toObjectSimple()
836 {
837     QScriptEngine eng;
838
839     QScriptValue undefined = eng.undefinedValue();
840     QCOMPARE(undefined.toObject().isValid(), false);
841     QScriptValue null = eng.nullValue();
842     QCOMPARE(null.toObject().isValid(), false);
843     QCOMPARE(QScriptValue().toObject().isValid(), false);
844
845     QScriptValue falskt = QScriptValue(&eng, false);
846     {
847         QScriptValue tmp = falskt.toObject();
848         QCOMPARE(tmp.isObject(), true);
849         QCOMPARE(falskt.isObject(), false);
850         QCOMPARE(tmp.toNumber(), falskt.toNumber());
851     }
852
853     QScriptValue sant = QScriptValue(&eng, true);
854     {
855         QScriptValue tmp = sant.toObject();
856         QCOMPARE(tmp.isObject(), true);
857         QCOMPARE(sant.isObject(), false);
858         QCOMPARE(tmp.toNumber(), sant.toNumber());
859     }
860
861     QScriptValue number = QScriptValue(&eng, 123.0);
862     {
863         QScriptValue tmp = number.toObject();
864         QCOMPARE(tmp.isObject(), true);
865         QCOMPARE(number.isObject(), false);
866         QCOMPARE(tmp.toNumber(), number.toNumber());
867     }
868
869     QScriptValue str = QScriptValue(&eng, QString("ciao"));
870     {
871         QScriptValue tmp = str.toObject();
872         QCOMPARE(tmp.isObject(), true);
873         QCOMPARE(str.isObject(), false);
874         QCOMPARE(tmp.toString(), str.toString());
875     }
876
877
878     QScriptValue object = eng.evaluate("new Object");
879     {
880         QScriptValue tmp = object.toObject();
881         QVERIFY(tmp.strictlyEquals(object));
882         QCOMPARE(tmp.isObject(), true);
883     }
884
885
886     // V2 constructors: in this case, you have to use QScriptEngine::toObject()
887     {
888         QScriptValue undefined = QScriptValue(QScriptValue::UndefinedValue);
889         QVERIFY(!undefined.toObject().isValid());
890         QVERIFY(!eng.toObject(undefined).isValid());
891         QVERIFY(!undefined.engine());
892
893         QScriptValue null = QScriptValue(QScriptValue::NullValue);
894         QVERIFY(!null.toObject().isValid());
895         QVERIFY(!eng.toObject(null).isValid());
896         QVERIFY(!null.engine());
897
898         QScriptValue falskt = QScriptValue(false);
899         QVERIFY(!falskt.toObject().isValid());
900         QCOMPARE(falskt.isObject(), false);
901         QVERIFY(!falskt.engine());
902         {
903             QScriptValue tmp = eng.toObject(falskt);
904             QVERIFY(tmp.isObject());
905             QVERIFY(tmp.toBool());
906             QVERIFY(!falskt.isObject());
907         }
908
909         QScriptValue sant = QScriptValue(true);
910         QVERIFY(!sant.toObject().isValid());
911         QCOMPARE(sant.isObject(), false);
912         QVERIFY(!sant.engine());
913         {
914             QScriptValue tmp = eng.toObject(sant);
915             QVERIFY(tmp.isObject());
916             QVERIFY(tmp.toBool());
917             QVERIFY(!sant.isObject());
918         }
919
920         QScriptValue number = QScriptValue(123.0);
921         QVERIFY(!number.toObject().isValid());
922         QVERIFY(!number.engine());
923         QCOMPARE(number.isObject(), false);
924         {
925             QScriptValue tmp = eng.toObject(number);
926             QVERIFY(tmp.isObject());
927             QCOMPARE(tmp.toInt32(), number.toInt32());
928             QVERIFY(!number.isObject());
929         }
930
931         QScriptValue str = QScriptValue(QString::fromLatin1("ciao"));
932         QVERIFY(!str.toObject().isValid());
933         QVERIFY(!str.engine());
934         QCOMPARE(str.isObject(), false);
935         {
936             QScriptValue tmp = eng.toObject(str);
937             QVERIFY(tmp.isObject());
938             QCOMPARE(tmp.toString(), QString::fromLatin1("ciao"));
939             QVERIFY(!str.isObject());
940         }
941     }
942 }
943
944 void tst_QScriptValue::setProperty_data()
945 {
946     QTest::addColumn<QScriptValue>("property");
947     QTest::addColumn<int>("flag");
948
949     QTest::newRow("int + keepExistingFlags") << QScriptValue(123456) << static_cast<int>(QScriptValue::KeepExistingFlags);
950     QTest::newRow("int + undeletable") << QScriptValue(123456) << static_cast<int>(QScriptValue::Undeletable);
951     QTest::newRow("int + readOnly") << QScriptValue(123456) << static_cast<int>(QScriptValue::ReadOnly);
952     QTest::newRow("int + readOnly|undeletable") << QScriptValue(123456) << static_cast<int>(QScriptValue::ReadOnly | QScriptValue::Undeletable);
953     QTest::newRow("int + skipInEnumeration") << QScriptValue(123456) << static_cast<int>(QScriptValue::SkipInEnumeration);
954     QTest::newRow("int + skipInEnumeration|readOnly") << QScriptValue(123456) << static_cast<int>(QScriptValue::SkipInEnumeration | QScriptValue::ReadOnly);
955     QTest::newRow("int + skipInEnumeration|undeletable") << QScriptValue(123456) << static_cast<int>(QScriptValue::SkipInEnumeration | QScriptValue::Undeletable);
956     QTest::newRow("int + skipInEnumeration|readOnly|undeletable") << QScriptValue(123456) << static_cast<int>(QScriptValue::SkipInEnumeration | QScriptValue::ReadOnly | QScriptValue::Undeletable);
957 }
958
959 void tst_QScriptValue::setProperty()
960 {
961     QFETCH(QScriptValue, property);
962     QFETCH(int, flag);
963     QScriptValue::PropertyFlags flags = static_cast<QScriptValue::PropertyFlag>(flag);
964
965     QScriptEngine engine;
966     QScriptValue object = engine.evaluate("o = new Object; o");
967     QScriptValue proto = engine.evaluate("p = new Object; o.__proto__ = p; p");
968     engine.evaluate("o.defined1 = 1");
969     engine.evaluate("o.defined2 = 1");
970     engine.evaluate("o[5] = 1");
971     engine.evaluate("p.overloaded1 = 1");
972     engine.evaluate("o.overloaded1 = 2");
973     engine.evaluate("p[6] = 1");
974     engine.evaluate("o[6] = 2");
975     engine.evaluate("p.overloaded2 = 1");
976     engine.evaluate("o.overloaded2 = 2");
977     engine.evaluate("p.overloaded3 = 1");
978     engine.evaluate("o.overloaded3 = 2");
979     engine.evaluate("p[7] = 1");
980     engine.evaluate("o[7] = 2");
981     engine.evaluate("p.overloaded4 = 1");
982     engine.evaluate("o.overloaded4 = 2");
983
984     // tries to set undefined property directly on object.
985     object.setProperty(QString::fromAscii("undefined1"), property, flags);
986     QVERIFY(engine.evaluate("o.undefined1").strictlyEquals(property));
987     object.setProperty(engine.toStringHandle("undefined2"), property, flags);
988     QVERIFY(object.property("undefined2").strictlyEquals(property));
989     object.setProperty(4, property, flags);
990     QVERIFY(object.property(4).strictlyEquals(property));
991
992     // tries to set defined property directly on object
993     object.setProperty("defined1", property, flags);
994     QVERIFY(engine.evaluate("o.defined1").strictlyEquals(property));
995     object.setProperty(engine.toStringHandle("defined2"), property, flags);
996     QVERIFY(object.property("defined2").strictlyEquals(property));
997     object.setProperty(5, property, flags);
998     QVERIFY(object.property(5).strictlyEquals(property));
999
1000     // tries to set overloaded property directly on object
1001     object.setProperty("overloaded1", property, flags);
1002     QVERIFY(engine.evaluate("o.overloaded1").strictlyEquals(property));
1003     object.setProperty(engine.toStringHandle("overloaded2"), property, flags);
1004     QVERIFY(object.property("overloaded2").strictlyEquals(property));
1005     object.setProperty(6, property, flags);
1006     QVERIFY(object.property(6).strictlyEquals(property));
1007
1008     // tries to set overloaded property directly on prototype
1009     proto.setProperty("overloaded3", property, flags);
1010     QVERIFY(!engine.evaluate("o.overloaded3").strictlyEquals(property));
1011     proto.setProperty(engine.toStringHandle("overloaded4"), property, flags);
1012     QVERIFY(!object.property("overloaded4").strictlyEquals(property));
1013     proto.setProperty(7, property, flags);
1014     QVERIFY(!object.property(7).strictlyEquals(property));
1015
1016     // tries to set undefined property directly on prototype
1017     proto.setProperty("undefined3", property, flags);
1018     QVERIFY(engine.evaluate("o.undefined3").strictlyEquals(property));
1019     proto.setProperty(engine.toStringHandle("undefined4"), property, flags);
1020     QVERIFY(object.property("undefined4").strictlyEquals(property));
1021     proto.setProperty(8, property, flags);
1022     QVERIFY(object.property(8).strictlyEquals(property));
1023
1024     bool readOnly = flags & QScriptValue::ReadOnly;
1025     bool skipInEnumeration = flags & QScriptValue::SkipInEnumeration;
1026     bool undeletable = flags & QScriptValue::Undeletable;
1027
1028     QVERIFY(readOnly == engine.evaluate("!Object.getOwnPropertyDescriptor(o, '4').writable").toBool());
1029     QEXPECT_FAIL("int + readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1030     QEXPECT_FAIL("int + readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1031     QEXPECT_FAIL("int + skipInEnumeration|readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1032     QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1033     QVERIFY(readOnly == engine.evaluate("!Object.getOwnPropertyDescriptor(o, '5').writable").toBool());
1034     QEXPECT_FAIL("int + readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1035     QEXPECT_FAIL("int + readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1036     QEXPECT_FAIL("int + skipInEnumeration|readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1037     QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1038     QVERIFY(readOnly == engine.evaluate("!Object.getOwnPropertyDescriptor(o, '6').writable").toBool());
1039     QEXPECT_FAIL("int + readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1040     QEXPECT_FAIL("int + readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1041     QEXPECT_FAIL("int + skipInEnumeration|readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1042     QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1043     QVERIFY(readOnly == engine.evaluate("!Object.getOwnPropertyDescriptor(p, '7').writable").toBool());
1044     QVERIFY(readOnly == engine.evaluate("!Object.getOwnPropertyDescriptor(p, '8').writable").toBool());
1045     QVERIFY(readOnly == engine.evaluate("!Object.getOwnPropertyDescriptor(o, 'undefined1').writable").toBool());
1046     QVERIFY(readOnly == engine.evaluate("!Object.getOwnPropertyDescriptor(o, 'undefined2').writable").toBool());
1047     QVERIFY(readOnly == engine.evaluate("!Object.getOwnPropertyDescriptor(p, 'undefined3').writable").toBool());
1048     QVERIFY(readOnly == engine.evaluate("!Object.getOwnPropertyDescriptor(p, 'undefined4').writable").toBool());
1049     QEXPECT_FAIL("int + readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1050     QEXPECT_FAIL("int + readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1051     QEXPECT_FAIL("int + skipInEnumeration|readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1052     QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1053     QVERIFY(readOnly == engine.evaluate("!Object.getOwnPropertyDescriptor(o, 'defined1').writable").toBool());
1054     QEXPECT_FAIL("int + readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1055     QEXPECT_FAIL("int + readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1056     QEXPECT_FAIL("int + skipInEnumeration|readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1057     QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1058     QVERIFY(readOnly == engine.evaluate("!Object.getOwnPropertyDescriptor(o, 'defined2').writable").toBool());
1059     QVERIFY(engine.evaluate("!Object.getOwnPropertyDescriptor(p, 'undefined1').writable").toBool());
1060     QVERIFY(engine.evaluate("!Object.getOwnPropertyDescriptor(p, 'undefined1').writable").toBool());
1061     QEXPECT_FAIL("int + readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1062     QEXPECT_FAIL("int + readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1063     QEXPECT_FAIL("int + skipInEnumeration|readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1064     QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1065     QVERIFY(readOnly == engine.evaluate("!Object.getOwnPropertyDescriptor(p, 'overloaded3').writable").toBool());
1066     QEXPECT_FAIL("int + readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1067     QEXPECT_FAIL("int + readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1068     QEXPECT_FAIL("int + skipInEnumeration|readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1069     QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1070     QVERIFY(readOnly == engine.evaluate("!Object.getOwnPropertyDescriptor(p, 'overloaded4').writable").toBool());
1071     QEXPECT_FAIL("int + readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1072     QEXPECT_FAIL("int + readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1073     QEXPECT_FAIL("int + skipInEnumeration|readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1074     QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1075     QVERIFY(readOnly == engine.evaluate("!Object.getOwnPropertyDescriptor(o, 'overloaded1').writable").toBool());
1076     QEXPECT_FAIL("int + readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1077     QEXPECT_FAIL("int + readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1078     QEXPECT_FAIL("int + skipInEnumeration|readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1079     QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1080     QVERIFY(readOnly == engine.evaluate("!Object.getOwnPropertyDescriptor(o, 'overloaded2').writable").toBool());
1081     QVERIFY(!engine.evaluate("!Object.getOwnPropertyDescriptor(o, 'overloaded3').writable").toBool());
1082     QVERIFY(!engine.evaluate("!Object.getOwnPropertyDescriptor(o, 'overloaded4').writable").toBool());
1083
1084     QVERIFY(undeletable == engine.evaluate("!Object.getOwnPropertyDescriptor(o, '4').configurable").toBool());
1085     QEXPECT_FAIL("int + undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1086     QEXPECT_FAIL("int + readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1087     QEXPECT_FAIL("int + skipInEnumeration|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1088     QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1089     QVERIFY(undeletable == engine.evaluate("!Object.getOwnPropertyDescriptor(o, '5').configurable").toBool());
1090     QEXPECT_FAIL("int + undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1091     QEXPECT_FAIL("int + readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1092     QEXPECT_FAIL("int + skipInEnumeration|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1093     QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1094     QVERIFY(undeletable == engine.evaluate("!Object.getOwnPropertyDescriptor(o, '6').configurable").toBool());
1095     QEXPECT_FAIL("int + undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1096     QEXPECT_FAIL("int + readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1097     QEXPECT_FAIL("int + skipInEnumeration|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1098     QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1099     QVERIFY(undeletable == engine.evaluate("!Object.getOwnPropertyDescriptor(p, '7').configurable").toBool());
1100     QVERIFY(undeletable == engine.evaluate("!Object.getOwnPropertyDescriptor(p, '8').configurable").toBool());
1101     QVERIFY(undeletable == engine.evaluate("!Object.getOwnPropertyDescriptor(o, 'undefined1').configurable").toBool());
1102     QVERIFY(undeletable == engine.evaluate("!Object.getOwnPropertyDescriptor(o, 'undefined2').configurable").toBool());
1103     QVERIFY(undeletable == engine.evaluate("!Object.getOwnPropertyDescriptor(p, 'undefined3').configurable").toBool());
1104     QVERIFY(undeletable == engine.evaluate("!Object.getOwnPropertyDescriptor(p, 'undefined4').configurable").toBool());
1105     QEXPECT_FAIL("int + undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1106     QEXPECT_FAIL("int + readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1107     QEXPECT_FAIL("int + skipInEnumeration|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1108     QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1109     QVERIFY(undeletable == engine.evaluate("!Object.getOwnPropertyDescriptor(o, 'defined1').configurable").toBool());
1110     QEXPECT_FAIL("int + undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1111     QEXPECT_FAIL("int + readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1112     QEXPECT_FAIL("int + skipInEnumeration|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1113     QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1114     QVERIFY(undeletable == engine.evaluate("!Object.getOwnPropertyDescriptor(o, 'defined2').configurable").toBool());
1115     QEXPECT_FAIL("int + undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1116     QEXPECT_FAIL("int + readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1117     QEXPECT_FAIL("int + skipInEnumeration|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1118     QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1119     QVERIFY(undeletable == engine.evaluate("!Object.getOwnPropertyDescriptor(o, 'overloaded1').configurable").toBool());
1120     QEXPECT_FAIL("int + undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1121     QEXPECT_FAIL("int + readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1122     QEXPECT_FAIL("int + skipInEnumeration|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1123     QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1124     QVERIFY(undeletable == engine.evaluate("!Object.getOwnPropertyDescriptor(o, 'overloaded2').configurable").toBool());
1125     QVERIFY(engine.evaluate("Object.getOwnPropertyDescriptor(p, 'overloaded1').configurable").toBool());
1126     QVERIFY(engine.evaluate("Object.getOwnPropertyDescriptor(p, 'overloaded2').configurable").toBool());
1127     QVERIFY(engine.evaluate("Object.getOwnPropertyDescriptor(o, 'overloaded3').configurable").toBool());
1128     QVERIFY(engine.evaluate("Object.getOwnPropertyDescriptor(o, 'overloaded4').configurable").toBool());
1129     QEXPECT_FAIL("int + undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1130     QEXPECT_FAIL("int + readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1131     QEXPECT_FAIL("int + skipInEnumeration|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1132     QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1133     QVERIFY(undeletable == engine.evaluate("!Object.getOwnPropertyDescriptor(p, 'overloaded3').configurable").toBool());
1134     QEXPECT_FAIL("int + undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1135     QEXPECT_FAIL("int + readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1136     QEXPECT_FAIL("int + skipInEnumeration|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1137     QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1138     QVERIFY(undeletable == engine.evaluate("!Object.getOwnPropertyDescriptor(p, 'overloaded4').configurable").toBool());
1139
1140     QVERIFY(skipInEnumeration != engine.evaluate("Object.getOwnPropertyDescriptor(o, '4').enumerable").toBool());
1141     QEXPECT_FAIL("int + skipInEnumeration", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1142     QEXPECT_FAIL("int + skipInEnumeration|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1143     QEXPECT_FAIL("int + skipInEnumeration|readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1144     QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1145     QVERIFY(skipInEnumeration != engine.evaluate("Object.getOwnPropertyDescriptor(o, '5').enumerable").toBool());
1146     QEXPECT_FAIL("int + skipInEnumeration", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1147     QEXPECT_FAIL("int + skipInEnumeration|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1148     QEXPECT_FAIL("int + skipInEnumeration|readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1149     QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1150     QVERIFY(skipInEnumeration != engine.evaluate("Object.getOwnPropertyDescriptor(o, '6').enumerable").toBool());
1151     QEXPECT_FAIL("int + skipInEnumeration", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1152     QEXPECT_FAIL("int + skipInEnumeration|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1153     QEXPECT_FAIL("int + skipInEnumeration|readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1154     QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1155     QVERIFY(skipInEnumeration != engine.evaluate("Object.getOwnPropertyDescriptor(p, '7').enumerable").toBool());
1156     QVERIFY(skipInEnumeration != engine.evaluate("Object.getOwnPropertyDescriptor(p, '8').enumerable").toBool());
1157     QVERIFY(skipInEnumeration != engine.evaluate("Object.getOwnPropertyDescriptor(o, 'undefined1').enumerable").toBool());
1158     QVERIFY(skipInEnumeration != engine.evaluate("Object.getOwnPropertyDescriptor(o, 'undefined2').enumerable").toBool());
1159     QVERIFY(skipInEnumeration != engine.evaluate("Object.getOwnPropertyDescriptor(p, 'undefined3').enumerable").toBool());
1160     QVERIFY(skipInEnumeration != engine.evaluate("Object.getOwnPropertyDescriptor(p, 'undefined4').enumerable").toBool());
1161     QEXPECT_FAIL("int + skipInEnumeration", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1162     QEXPECT_FAIL("int + skipInEnumeration|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1163     QEXPECT_FAIL("int + skipInEnumeration|readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1164     QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1165     QVERIFY(skipInEnumeration != engine.evaluate("Object.getOwnPropertyDescriptor(o, 'overloaded1').enumerable").toBool());
1166     QEXPECT_FAIL("int + skipInEnumeration", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1167     QEXPECT_FAIL("int + skipInEnumeration|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1168     QEXPECT_FAIL("int + skipInEnumeration|readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1169     QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1170     QVERIFY(skipInEnumeration != engine.evaluate("Object.getOwnPropertyDescriptor(o, 'overloaded2').enumerable").toBool());
1171     QVERIFY(engine.evaluate("p.propertyIsEnumerable('overloaded1')").toBool());
1172     QVERIFY(engine.evaluate("p.propertyIsEnumerable('overloaded2')").toBool());
1173     QVERIFY(engine.evaluate("o.propertyIsEnumerable('overloaded3')").toBool());
1174     QVERIFY(engine.evaluate("o.propertyIsEnumerable('overloaded4')").toBool());
1175     QEXPECT_FAIL("int + skipInEnumeration", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1176     QEXPECT_FAIL("int + skipInEnumeration|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1177     QEXPECT_FAIL("int + skipInEnumeration|readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1178     QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1179     QVERIFY(skipInEnumeration != engine.evaluate("p.propertyIsEnumerable('overloaded3')").toBool());
1180     QEXPECT_FAIL("int + skipInEnumeration", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1181     QEXPECT_FAIL("int + skipInEnumeration|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1182     QEXPECT_FAIL("int + skipInEnumeration|readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1183     QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1184     QVERIFY(skipInEnumeration != engine.evaluate("p.propertyIsEnumerable('overloaded4')").toBool());
1185     QEXPECT_FAIL("int + skipInEnumeration", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1186     QEXPECT_FAIL("int + skipInEnumeration|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1187     QEXPECT_FAIL("int + skipInEnumeration|readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1188     QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1189     QVERIFY(skipInEnumeration != engine.evaluate("o.propertyIsEnumerable('defined1')").toBool());
1190     QEXPECT_FAIL("int + skipInEnumeration", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1191     QEXPECT_FAIL("int + skipInEnumeration|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1192     QEXPECT_FAIL("int + skipInEnumeration|readOnly", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1193     QEXPECT_FAIL("int + skipInEnumeration|readOnly|undeletable", "WebKit bug: 40613 (The JSObjectSetProperty doesn't overwrite property flags)", Continue);
1194     QVERIFY(skipInEnumeration != engine.evaluate("o.propertyIsEnumerable('defined2')").toBool());
1195 }
1196
1197 void tst_QScriptValue::propertyFlag_data()
1198 {
1199     QTest::addColumn<QString>("name");
1200     QTest::addColumn<int>("flag");
1201
1202     QTest::newRow("?Cr@jzi!%$") << "?Cr@jzi!%$" << static_cast<int>(0);
1203     QTest::newRow("ReadOnly") << "ReadOnly" << static_cast<int>(QScriptValue::ReadOnly);
1204     QTest::newRow("Undeletable") << "Undeletable" << static_cast<int>(QScriptValue::Undeletable);
1205     QTest::newRow("SkipInEnumeration") << "SkipInEnumeration" << static_cast<int>(QScriptValue::SkipInEnumeration);
1206     QTest::newRow("ReadOnly | Undeletable") << "ReadOnly_Undeletable" << static_cast<int>(QScriptValue::ReadOnly | QScriptValue::Undeletable);
1207     QTest::newRow("ReadOnly | SkipInEnumeration") << "ReadOnly_SkipInEnumeration" << static_cast<int>(QScriptValue::ReadOnly | QScriptValue::SkipInEnumeration);
1208     QTest::newRow("Undeletable | SkipInEnumeration") << "Undeletable_SkipInEnumeration" << static_cast<int>(QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
1209     QTest::newRow("ReadOnly | Undeletable | SkipInEnumeration") << "ReadOnly_Undeletable_SkipInEnumeration" << static_cast<int>(QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
1210 }
1211
1212 void tst_QScriptValue::propertyFlag()
1213 {
1214     QScriptEngine engine;
1215     QFETCH(QString, name);
1216     QFETCH(int, flag);
1217     const QScriptString nameHandle = engine.toStringHandle(name);
1218     const QString protoName = "proto" + name;
1219     const QScriptString protoNameHandle = engine.toStringHandle(protoName);
1220
1221     QScriptValue proto = engine.newObject();
1222     QScriptValue object = engine.newObject();
1223     object.setPrototype(proto);
1224
1225     proto.setProperty(protoName, QScriptValue(124816), QScriptValue::PropertyFlag(flag));
1226     object.setProperty(name, QScriptValue(124816), QScriptValue::PropertyFlag(flag));
1227
1228     // Check using QString name
1229     QCOMPARE(object.propertyFlags(name), QScriptValue::PropertyFlag(flag));
1230     QCOMPARE(object.propertyFlags(protoName, QScriptValue::ResolvePrototype), QScriptValue::PropertyFlag(flag));
1231     QVERIFY(!object.propertyFlags(protoName, QScriptValue::ResolveLocal));
1232
1233     // Check using QScriptString name
1234     QCOMPARE(object.propertyFlags(nameHandle), QScriptValue::PropertyFlag(flag));
1235     QCOMPARE(object.propertyFlags(protoNameHandle, QScriptValue::ResolvePrototype), QScriptValue::PropertyFlag(flag));
1236     QVERIFY(!object.propertyFlags(protoNameHandle, QScriptValue::ResolveLocal));
1237 }
1238
1239 void tst_QScriptValue::globalObjectChanges()
1240 {
1241     // API functionality shouldn't depend on Global Object.
1242     QScriptEngine engine;
1243     QScriptValue array = engine.newArray();
1244     QScriptValue error = engine.evaluate("new Error");
1245     QScriptValue object = engine.newObject();
1246
1247     object.setProperty("foo", 512);
1248
1249     // Remove properties form global object.
1250     engine.evaluate("delete Object; delete Error; delete Array;");
1251
1252     QVERIFY(array.isArray());
1253     QVERIFY(error.isError());
1254     QVERIFY(object.isObject());
1255
1256     QVERIFY(object.property("foo").isValid());
1257     QVERIFY(object.property("foo", QScriptValue::ResolveLocal).isValid());
1258     object.setProperty("foo", QScriptValue());
1259     QVERIFY(!object.property("foo").isValid());
1260     QVERIFY(!object.property("foo", QScriptValue::ResolveLocal).isValid());
1261 }
1262
1263 void tst_QScriptValue::assignAndCopyConstruct_data()
1264 {
1265     QTest::addColumn<QScriptValue>("value");
1266     if (m_engine)
1267         delete m_engine;
1268     m_engine = new QScriptEngine;
1269     // Copy & assign code is the same for all types, so it is enough to check only a few value.
1270     for (unsigned i = 0; i < 10; ++i) {
1271         QPair<QString, QScriptValue> testcase = initScriptValues(i);
1272         QTest::newRow(testcase.first.toAscii().constData()) << testcase.second;
1273     }
1274 }
1275
1276 void tst_QScriptValue::assignAndCopyConstruct()
1277 {
1278     QFETCH(QScriptValue, value);
1279     QScriptValue copy(value);
1280     QEXPECT_FAIL("QScriptValue(QScriptValue::NullValue)", "FIXME: WebKit bug 43038", Abort);
1281     QEXPECT_FAIL("QScriptValue(QScriptValue::UndefinedValue)", "FIXME: WebKit bug 43038", Abort);
1282     QCOMPARE(copy.strictlyEquals(value), !value.isNumber() || !qIsNaN(value.toNumber()));
1283     QCOMPARE(copy.engine(), value.engine());
1284
1285     QScriptValue assigned = copy;
1286     QCOMPARE(assigned.strictlyEquals(value), !copy.isNumber() || !qIsNaN(copy.toNumber()));
1287     QCOMPARE(assigned.engine(), assigned.engine());
1288
1289     QScriptValue other(!value.toBool());
1290     assigned = other;
1291     QVERIFY(!assigned.strictlyEquals(copy));
1292     QVERIFY(assigned.strictlyEquals(other));
1293     QCOMPARE(assigned.engine(), other.engine());
1294 }
1295
1296 QTEST_MAIN(tst_QScriptValue)