]>
Commit | Line | Data |
---|---|---|
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) |