0
+ − 1
/****************************************************************************
+ − 2
**
4
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 3
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
0
+ − 4
** All rights reserved.
+ − 5
** Contact: Nokia Corporation (qt-info@nokia.com)
+ − 6
**
+ − 7
** This file is part of the test suite of the Qt Toolkit.
+ − 8
**
+ − 9
** $QT_BEGIN_LICENSE:LGPL$
+ − 10
** No Commercial Usage
+ − 11
** This file contains pre-release code and may not be distributed.
+ − 12
** You may use this file in accordance with the terms and conditions
+ − 13
** contained in the Technology Preview License Agreement accompanying
+ − 14
** this package.
+ − 15
**
+ − 16
** GNU Lesser General Public License Usage
+ − 17
** Alternatively, this file may be used under the terms of the GNU Lesser
+ − 18
** General Public License version 2.1 as published by the Free Software
+ − 19
** Foundation and appearing in the file LICENSE.LGPL included in the
+ − 20
** packaging of this file. Please review the following information to
+ − 21
** ensure the GNU Lesser General Public License version 2.1 requirements
+ − 22
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+ − 23
**
+ − 24
** In addition, as a special exception, Nokia gives you certain additional
+ − 25
** rights. These rights are described in the Nokia Qt LGPL Exception
+ − 26
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+ − 27
**
+ − 28
** If you have questions regarding the use of this file, please contact
+ − 29
** Nokia at qt-info@nokia.com.
+ − 30
**
+ − 31
**
+ − 32
**
+ − 33
**
+ − 34
**
+ − 35
**
+ − 36
**
+ − 37
**
+ − 38
** $QT_END_LICENSE$
+ − 39
**
+ − 40
****************************************************************************/
+ − 41
+ − 42
+ − 43
#include <QtTest/QtTest>
+ − 44
+ − 45
#include <qscriptengine.h>
+ − 46
#include <qscriptengineagent.h>
3
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 47
#include <qscriptprogram.h>
0
+ − 48
#include <qscriptvalueiterator.h>
+ − 49
#include <qgraphicsitem.h>
+ − 50
#include <qstandarditemmodel.h>
+ − 51
#include <QtCore/qnumeric.h>
+ − 52
#include <stdlib.h>
+ − 53
+ − 54
Q_DECLARE_METATYPE(QList<int>)
+ − 55
Q_DECLARE_METATYPE(QObjectList)
3
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 56
Q_DECLARE_METATYPE(QScriptProgram)
0
+ − 57
+ − 58
//TESTED_CLASS=
+ − 59
//TESTED_FILES=
+ − 60
+ − 61
#if defined(Q_OS_SYMBIAN)
+ − 62
# define STRINGIFY(x) #x
+ − 63
# define TOSTRING(x) STRINGIFY(x)
+ − 64
# define SRCDIR "C:/Private/" TOSTRING(SYMBIAN_SRCDIR_UID)
+ − 65
#endif
+ − 66
+ − 67
// The JavaScriptCore GC marks the C stack. To try to ensure that there is
+ − 68
// no JSObject* left in stack memory by the compiler, we call this function
+ − 69
// to zap some bytes of memory before calling collectGarbage().
+ − 70
static void zapSomeStack()
+ − 71
{
+ − 72
char buf[4096];
+ − 73
memset(buf, 0, sizeof(buf));
+ − 74
}
+ − 75
+ − 76
static void collectGarbage_helper(QScriptEngine &eng)
+ − 77
{
+ − 78
zapSomeStack();
+ − 79
eng.collectGarbage();
+ − 80
}
+ − 81
+ − 82
class tst_QScriptEngine : public QObject
+ − 83
{
+ − 84
Q_OBJECT
+ − 85
+ − 86
public:
+ − 87
tst_QScriptEngine();
+ − 88
virtual ~tst_QScriptEngine();
+ − 89
+ − 90
private slots:
+ − 91
void constructWithParent();
+ − 92
void currentContext();
+ − 93
void pushPopContext();
+ − 94
void getSetDefaultPrototype();
+ − 95
void newFunction();
+ − 96
void newObject();
+ − 97
void newArray();
+ − 98
void newVariant();
+ − 99
void newRegExp();
+ − 100
void newDate();
+ − 101
void newQObject();
+ − 102
void newQMetaObject();
+ − 103
void newActivationObject();
+ − 104
void getSetGlobalObject();
+ − 105
void globalObjectProperties();
+ − 106
void globalObjectGetterSetterProperty();
14
+ − 107
void customGlobalObjectWithPrototype();
+ − 108
void globalObjectWithCustomPrototype();
0
+ − 109
void builtinFunctionNames_data();
+ − 110
void builtinFunctionNames();
+ − 111
void checkSyntax_data();
+ − 112
void checkSyntax();
+ − 113
void canEvaluate_data();
+ − 114
void canEvaluate();
+ − 115
void evaluate_data();
+ − 116
void evaluate();
+ − 117
void nestedEvaluate();
+ − 118
void uncaughtException();
+ − 119
void errorMessage_QT679();
+ − 120
void valueConversion();
+ − 121
void importExtension();
+ − 122
void infiniteRecursion();
+ − 123
void castWithPrototypeChain();
+ − 124
void castWithMultipleInheritance();
+ − 125
void collectGarbage();
+ − 126
void gcWithNestedDataStructure();
+ − 127
void processEventsWhileRunning();
+ − 128
void throwErrorFromProcessEvents();
+ − 129
void stacktrace();
+ − 130
void numberParsing_data();
+ − 131
void numberParsing();
+ − 132
void automaticSemicolonInsertion();
+ − 133
void abortEvaluation();
+ − 134
void isEvaluating();
+ − 135
void printFunctionWithCustomHandler();
+ − 136
void printThrowsException();
+ − 137
void errorConstructors();
+ − 138
void argumentsProperty();
+ − 139
void numberClass();
+ − 140
void forInStatement();
+ − 141
void functionExpression();
+ − 142
void stringObjects();
+ − 143
void getterSetterThisObject();
+ − 144
void continueInSwitch();
+ − 145
void readOnlyPrototypeProperty();
+ − 146
void toObject();
+ − 147
void reservedWords_data();
+ − 148
void reservedWords();
+ − 149
void futureReservedWords_data();
+ − 150
void futureReservedWords();
+ − 151
void throwInsideWithStatement();
+ − 152
void getSetAgent();
+ − 153
void reentrancy();
+ − 154
void incDecNonObjectProperty();
8
+ − 155
void installTranslatorFunctions_data();
0
+ − 156
void installTranslatorFunctions();
14
+ − 157
void translateScript();
+ − 158
void translateWithInvalidArgs_data();
+ − 159
void translateWithInvalidArgs();
+ − 160
void translationContext_data();
+ − 161
void translationContext();
0
+ − 162
void functionScopes();
+ − 163
void nativeFunctionScopes();
3
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 164
void evaluateProgram();
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 165
void collectGarbageAfterConnect();
0
+ − 166
+ − 167
void qRegExpInport_data();
+ − 168
void qRegExpInport();
+ − 169
};
+ − 170
+ − 171
tst_QScriptEngine::tst_QScriptEngine()
+ − 172
{
+ − 173
}
+ − 174
+ − 175
tst_QScriptEngine::~tst_QScriptEngine()
+ − 176
{
+ − 177
}
+ − 178
+ − 179
void tst_QScriptEngine::constructWithParent()
+ − 180
{
+ − 181
QPointer<QScriptEngine> ptr;
+ − 182
{
+ − 183
QObject obj;
+ − 184
QScriptEngine *engine = new QScriptEngine(&obj);
+ − 185
ptr = engine;
+ − 186
}
+ − 187
QVERIFY(ptr == 0);
+ − 188
}
+ − 189
+ − 190
void tst_QScriptEngine::currentContext()
+ − 191
{
+ − 192
QScriptEngine eng;
+ − 193
QScriptContext *globalCtx = eng.currentContext();
+ − 194
QVERIFY(globalCtx != 0);
+ − 195
QVERIFY(globalCtx->parentContext() == 0);
+ − 196
QCOMPARE(globalCtx->engine(), &eng);
+ − 197
QCOMPARE(globalCtx->argumentCount(), 0);
+ − 198
QCOMPARE(globalCtx->backtrace().size(), 1);
+ − 199
QVERIFY(!globalCtx->isCalledAsConstructor());
+ − 200
QVERIFY(!globalCtx->callee().isValid());
+ − 201
QCOMPARE(globalCtx->state(), QScriptContext::NormalState);
+ − 202
QVERIFY(globalCtx->thisObject().strictlyEquals(eng.globalObject()));
+ − 203
QVERIFY(globalCtx->activationObject().strictlyEquals(eng.globalObject()));
+ − 204
QVERIFY(globalCtx->argumentsObject().isObject());
+ − 205
}
+ − 206
+ − 207
void tst_QScriptEngine::pushPopContext()
+ − 208
{
+ − 209
QScriptEngine eng;
+ − 210
QScriptContext *globalCtx = eng.currentContext();
+ − 211
QScriptContext *ctx = eng.pushContext();
+ − 212
QVERIFY(ctx != 0);
+ − 213
QCOMPARE(ctx->parentContext(), globalCtx);
+ − 214
QVERIFY(!ctx->isCalledAsConstructor());
+ − 215
QVERIFY(!ctx->callee().isValid());
+ − 216
QVERIFY(ctx->thisObject().strictlyEquals(eng.globalObject()));
+ − 217
QCOMPARE(ctx->argumentCount(), 0);
+ − 218
QCOMPARE(ctx->backtrace().size(), 2);
+ − 219
QCOMPARE(ctx->engine(), &eng);
+ − 220
QCOMPARE(ctx->state(), QScriptContext::NormalState);
+ − 221
QVERIFY(ctx->activationObject().isObject());
+ − 222
QVERIFY(ctx->argumentsObject().isObject());
+ − 223
+ − 224
QScriptContext *ctx2 = eng.pushContext();
+ − 225
QVERIFY(ctx2 != 0);
+ − 226
QCOMPARE(ctx2->parentContext(), ctx);
+ − 227
QVERIFY(!ctx2->activationObject().strictlyEquals(ctx->activationObject()));
+ − 228
QVERIFY(!ctx2->argumentsObject().strictlyEquals(ctx->argumentsObject()));
+ − 229
+ − 230
eng.popContext();
+ − 231
eng.popContext();
+ − 232
QTest::ignoreMessage(QtWarningMsg, "QScriptEngine::popContext() doesn't match with pushContext()");
+ − 233
eng.popContext(); // ignored
+ − 234
QTest::ignoreMessage(QtWarningMsg, "QScriptEngine::popContext() doesn't match with pushContext()");
+ − 235
eng.popContext(); // ignored
+ − 236
}
+ − 237
+ − 238
static QScriptValue myFunction(QScriptContext *, QScriptEngine *eng)
+ − 239
{
+ − 240
return eng->nullValue();
+ − 241
}
+ − 242
+ − 243
static QScriptValue myFunctionWithVoidArg(QScriptContext *, QScriptEngine *eng, void *)
+ − 244
{
+ − 245
return eng->nullValue();
+ − 246
}
+ − 247
+ − 248
static QScriptValue myThrowingFunction(QScriptContext *ctx, QScriptEngine *)
+ − 249
{
+ − 250
return ctx->throwError("foo");
+ − 251
}
+ − 252
+ − 253
void tst_QScriptEngine::newFunction()
+ − 254
{
+ − 255
QScriptEngine eng;
+ − 256
{
+ − 257
QScriptValue fun = eng.newFunction(myFunction);
+ − 258
QCOMPARE(fun.isValid(), true);
+ − 259
QCOMPARE(fun.isFunction(), true);
+ − 260
QCOMPARE(fun.isObject(), true);
+ − 261
QCOMPARE(fun.scriptClass(), (QScriptClass*)0);
+ − 262
// a prototype property is automatically constructed
+ − 263
{
+ − 264
QScriptValue prot = fun.property("prototype", QScriptValue::ResolveLocal);
+ − 265
QVERIFY(prot.isObject());
+ − 266
QVERIFY(prot.property("constructor").strictlyEquals(fun));
+ − 267
QCOMPARE(fun.propertyFlags("prototype"), QScriptValue::Undeletable);
+ − 268
QCOMPARE(prot.propertyFlags("constructor"), QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
+ − 269
}
+ − 270
// prototype should be Function.prototype
+ − 271
QCOMPARE(fun.prototype().isValid(), true);
+ − 272
QCOMPARE(fun.prototype().isFunction(), true);
+ − 273
QCOMPARE(fun.prototype().strictlyEquals(eng.evaluate("Function.prototype")), true);
+ − 274
+ − 275
QCOMPARE(fun.call().isNull(), true);
+ − 276
QCOMPARE(fun.construct().isObject(), true);
+ − 277
}
+ − 278
+ − 279
// the overload that takes a void*
+ − 280
{
+ − 281
QScriptValue fun = eng.newFunction(myFunctionWithVoidArg, (void*)this);
+ − 282
QVERIFY(fun.isFunction());
+ − 283
QCOMPARE(fun.scriptClass(), (QScriptClass*)0);
+ − 284
// a prototype property is automatically constructed
+ − 285
{
+ − 286
QScriptValue prot = fun.property("prototype", QScriptValue::ResolveLocal);
+ − 287
QVERIFY(prot.isObject());
+ − 288
QVERIFY(prot.property("constructor").strictlyEquals(fun));
+ − 289
QCOMPARE(fun.propertyFlags("prototype"), QScriptValue::Undeletable);
+ − 290
QCOMPARE(prot.propertyFlags("constructor"), QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
+ − 291
}
+ − 292
// prototype should be Function.prototype
+ − 293
QCOMPARE(fun.prototype().isValid(), true);
+ − 294
QCOMPARE(fun.prototype().isFunction(), true);
+ − 295
QCOMPARE(fun.prototype().strictlyEquals(eng.evaluate("Function.prototype")), true);
+ − 296
+ − 297
QCOMPARE(fun.call().isNull(), true);
+ − 298
QCOMPARE(fun.construct().isObject(), true);
+ − 299
}
+ − 300
+ − 301
// the overload that takes a prototype
+ − 302
{
+ − 303
QScriptValue proto = eng.newObject();
+ − 304
QScriptValue fun = eng.newFunction(myFunction, proto);
+ − 305
QCOMPARE(fun.isValid(), true);
+ − 306
QCOMPARE(fun.isFunction(), true);
+ − 307
QCOMPARE(fun.isObject(), true);
+ − 308
// internal prototype should be Function.prototype
+ − 309
QCOMPARE(fun.prototype().isValid(), true);
+ − 310
QCOMPARE(fun.prototype().isFunction(), true);
+ − 311
QCOMPARE(fun.prototype().strictlyEquals(eng.evaluate("Function.prototype")), true);
+ − 312
// public prototype should be the one we passed
+ − 313
QCOMPARE(fun.property("prototype").strictlyEquals(proto), true);
+ − 314
QCOMPARE(fun.propertyFlags("prototype"), QScriptValue::Undeletable);
+ − 315
QCOMPARE(proto.property("constructor").strictlyEquals(fun), true);
+ − 316
QCOMPARE(proto.propertyFlags("constructor"),
+ − 317
QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
+ − 318
+ − 319
QCOMPARE(fun.call().isNull(), true);
+ − 320
QCOMPARE(fun.construct().isObject(), true);
+ − 321
}
+ − 322
}
+ − 323
+ − 324
void tst_QScriptEngine::newObject()
+ − 325
{
+ − 326
QScriptEngine eng;
+ − 327
QScriptValue object = eng.newObject();
+ − 328
QCOMPARE(object.isValid(), true);
+ − 329
QCOMPARE(object.isObject(), true);
+ − 330
QCOMPARE(object.isFunction(), false);
+ − 331
QCOMPARE(object.scriptClass(), (QScriptClass*)0);
+ − 332
// prototype should be Object.prototype
+ − 333
QCOMPARE(object.prototype().isValid(), true);
+ − 334
QCOMPARE(object.prototype().isObject(), true);
+ − 335
QCOMPARE(object.prototype().strictlyEquals(eng.evaluate("Object.prototype")), true);
+ − 336
}
+ − 337
+ − 338
void tst_QScriptEngine::newArray()
+ − 339
{
+ − 340
QScriptEngine eng;
+ − 341
QScriptValue array = eng.newArray();
+ − 342
QCOMPARE(array.isValid(), true);
+ − 343
QCOMPARE(array.isArray(), true);
+ − 344
QCOMPARE(array.isObject(), true);
+ − 345
QVERIFY(!array.isFunction());
+ − 346
QCOMPARE(array.scriptClass(), (QScriptClass*)0);
+ − 347
// prototype should be Array.prototype
+ − 348
QCOMPARE(array.prototype().isValid(), true);
+ − 349
QCOMPARE(array.prototype().isArray(), true);
+ − 350
QCOMPARE(array.prototype().strictlyEquals(eng.evaluate("Array.prototype")), true);
+ − 351
+ − 352
// task 218092
+ − 353
{
+ − 354
QScriptValue ret = eng.evaluate("[].splice(0, 0, 'a')");
+ − 355
QVERIFY(ret.isArray());
+ − 356
QCOMPARE(ret.property("length").toInt32(), 0);
+ − 357
}
+ − 358
{
+ − 359
QScriptValue ret = eng.evaluate("['a'].splice(0, 1, 'b')");
+ − 360
QVERIFY(ret.isArray());
+ − 361
QCOMPARE(ret.property("length").toInt32(), 1);
+ − 362
}
+ − 363
{
+ − 364
QScriptValue ret = eng.evaluate("['a', 'b'].splice(0, 1, 'c')");
+ − 365
QVERIFY(ret.isArray());
+ − 366
QCOMPARE(ret.property("length").toInt32(), 1);
+ − 367
}
+ − 368
{
+ − 369
QScriptValue ret = eng.evaluate("['a', 'b', 'c'].splice(0, 2, 'd')");
+ − 370
QVERIFY(ret.isArray());
+ − 371
QCOMPARE(ret.property("length").toInt32(), 2);
+ − 372
}
+ − 373
{
+ − 374
QScriptValue ret = eng.evaluate("['a', 'b', 'c'].splice(1, 2, 'd', 'e', 'f')");
+ − 375
QVERIFY(ret.isArray());
+ − 376
QCOMPARE(ret.property("length").toInt32(), 2);
+ − 377
}
+ − 378
+ − 379
// task 233836
+ − 380
{
+ − 381
QScriptValue ret = eng.evaluate("a = new Array(4294967295); a.push('foo')");
+ − 382
QVERIFY(ret.isNumber());
+ − 383
QCOMPARE(ret.toInt32(), 0);
+ − 384
QCOMPARE(eng.evaluate("a[4294967295]").toString(), QString::fromLatin1("foo"));
+ − 385
}
+ − 386
{
+ − 387
QScriptValue ret = eng.newArray(0xFFFFFFFF);
+ − 388
QCOMPARE(ret.property("length").toUInt32(), uint(0xFFFFFFFF));
+ − 389
ret.setProperty(0xFFFFFFFF, 123);
+ − 390
QCOMPARE(ret.property("length").toUInt32(), uint(0xFFFFFFFF));
+ − 391
QVERIFY(ret.property(0xFFFFFFFF).isNumber());
+ − 392
QCOMPARE(ret.property(0xFFFFFFFF).toInt32(), 123);
+ − 393
ret.setProperty(123, 456);
+ − 394
QCOMPARE(ret.property("length").toUInt32(), uint(0xFFFFFFFF));
+ − 395
QVERIFY(ret.property(123).isNumber());
+ − 396
QCOMPARE(ret.property(123).toInt32(), 456);
+ − 397
}
+ − 398
}
+ − 399
+ − 400
void tst_QScriptEngine::newVariant()
+ − 401
{
+ − 402
QScriptEngine eng;
+ − 403
{
+ − 404
QScriptValue opaque = eng.newVariant(QVariant());
+ − 405
QCOMPARE(opaque.isValid(), true);
+ − 406
QCOMPARE(opaque.isVariant(), true);
+ − 407
QVERIFY(!opaque.isFunction());
+ − 408
QCOMPARE(opaque.isObject(), true);
+ − 409
QCOMPARE(opaque.prototype().isValid(), true);
+ − 410
QCOMPARE(opaque.prototype().isVariant(), true);
+ − 411
QVERIFY(opaque.property("valueOf").call(opaque).isUndefined());
+ − 412
}
+ − 413
// default prototype should be set automatically
+ − 414
{
+ − 415
QScriptValue proto = eng.newObject();
+ − 416
eng.setDefaultPrototype(qMetaTypeId<QString>(), proto);
+ − 417
QScriptValue ret = eng.newVariant(QVariant(QString::fromLatin1("hello")));
+ − 418
QVERIFY(ret.isVariant());
+ − 419
QCOMPARE(ret.scriptClass(), (QScriptClass*)0);
+ − 420
QVERIFY(ret.prototype().strictlyEquals(proto));
+ − 421
eng.setDefaultPrototype(qMetaTypeId<QString>(), QScriptValue());
+ − 422
QScriptValue ret2 = eng.newVariant(QVariant(QString::fromLatin1("hello")));
+ − 423
QVERIFY(ret2.isVariant());
+ − 424
QVERIFY(!ret2.prototype().strictlyEquals(proto));
+ − 425
}
+ − 426
// "promote" plain object to variant
+ − 427
{
+ − 428
QScriptValue object = eng.newObject();
+ − 429
object.setProperty("foo", eng.newObject());
+ − 430
object.setProperty("bar", object.property("foo"));
+ − 431
QVERIFY(object.property("foo").isObject());
+ − 432
QVERIFY(!object.property("foo").isVariant());
+ − 433
QScriptValue originalProto = object.property("foo").prototype();
+ − 434
QScriptValue ret = eng.newVariant(object.property("foo"), QVariant(123));
+ − 435
QVERIFY(ret.isValid());
+ − 436
QVERIFY(ret.strictlyEquals(object.property("foo")));
+ − 437
QVERIFY(ret.isVariant());
+ − 438
QVERIFY(object.property("foo").isVariant());
+ − 439
QVERIFY(object.property("bar").isVariant());
+ − 440
QCOMPARE(ret.toVariant(), QVariant(123));
+ − 441
QVERIFY(ret.prototype().strictlyEquals(originalProto));
+ − 442
}
+ − 443
// replace value of existing object
+ − 444
{
+ − 445
QScriptValue object = eng.newVariant(QVariant(123));
+ − 446
QScriptValue ret = eng.newVariant(object, QVariant(456));
+ − 447
QVERIFY(ret.isValid());
+ − 448
QVERIFY(ret.strictlyEquals(object));
+ − 449
QVERIFY(ret.isVariant());
+ − 450
QCOMPARE(ret.toVariant(), QVariant(456));
+ − 451
}
+ − 452
+ − 453
// valueOf() and toString()
+ − 454
{
+ − 455
QScriptValue object = eng.newVariant(QVariant(123));
+ − 456
QScriptValue value = object.property("valueOf").call(object);
+ − 457
QVERIFY(value.isNumber());
+ − 458
QCOMPARE(value.toInt32(), 123);
+ − 459
QCOMPARE(object.toString(), QString::fromLatin1("123"));
+ − 460
QCOMPARE(object.toVariant().toString(), object.toString());
+ − 461
}
+ − 462
{
+ − 463
QScriptValue object = eng.newVariant(QVariant(QString::fromLatin1("hello")));
+ − 464
QScriptValue value = object.property("valueOf").call(object);
+ − 465
QVERIFY(value.isString());
+ − 466
QCOMPARE(value.toString(), QString::fromLatin1("hello"));
+ − 467
QCOMPARE(object.toString(), QString::fromLatin1("hello"));
+ − 468
QCOMPARE(object.toVariant().toString(), object.toString());
+ − 469
}
+ − 470
{
+ − 471
QScriptValue object = eng.newVariant(QVariant(false));
+ − 472
QScriptValue value = object.property("valueOf").call(object);
+ − 473
QVERIFY(value.isBoolean());
+ − 474
QCOMPARE(value.toBoolean(), false);
+ − 475
QCOMPARE(object.toString(), QString::fromLatin1("false"));
+ − 476
QCOMPARE(object.toVariant().toString(), object.toString());
+ − 477
}
+ − 478
{
+ − 479
QScriptValue object = eng.newVariant(QVariant(QPoint(10, 20)));
+ − 480
QScriptValue value = object.property("valueOf").call(object);
+ − 481
QVERIFY(value.isObject());
+ − 482
QVERIFY(value.strictlyEquals(object));
+ − 483
QCOMPARE(object.toString(), QString::fromLatin1("QVariant(QPoint)"));
+ − 484
}
+ − 485
}
+ − 486
+ − 487
void tst_QScriptEngine::newRegExp()
+ − 488
{
+ − 489
QScriptEngine eng;
+ − 490
for (int x = 0; x < 2; ++x) {
+ − 491
QScriptValue rexp;
+ − 492
if (x == 0)
+ − 493
rexp = eng.newRegExp("foo", "bar");
+ − 494
else
+ − 495
rexp = eng.newRegExp(QRegExp("foo"));
+ − 496
QCOMPARE(rexp.isValid(), true);
+ − 497
QCOMPARE(rexp.isRegExp(), true);
+ − 498
QCOMPARE(rexp.isObject(), true);
+ − 499
QVERIFY(rexp.isFunction()); // in JSC, RegExp objects are callable
+ − 500
// prototype should be RegExp.prototype
+ − 501
QCOMPARE(rexp.prototype().isValid(), true);
+ − 502
QCOMPARE(rexp.prototype().isObject(), true);
+ − 503
QCOMPARE(rexp.prototype().isRegExp(), false);
+ − 504
QCOMPARE(rexp.prototype().strictlyEquals(eng.evaluate("RegExp.prototype")), true);
+ − 505
+ − 506
QCOMPARE(rexp.toRegExp().pattern(), QRegExp("foo").pattern());
+ − 507
}
+ − 508
{
+ − 509
QScriptValue r = eng.evaluate("/foo/gim");
+ − 510
QVERIFY(r.isRegExp());
+ − 511
QCOMPARE(r.toString(), QString::fromLatin1("/foo/gim"));
+ − 512
+ − 513
QScriptValue rxCtor = eng.globalObject().property("RegExp");
+ − 514
QScriptValue r2 = rxCtor.call(QScriptValue(), QScriptValueList() << r);
+ − 515
QVERIFY(r2.isRegExp());
+ − 516
QVERIFY(r2.strictlyEquals(r));
+ − 517
+ − 518
QScriptValue r3 = rxCtor.call(QScriptValue(), QScriptValueList() << r << "gim");
+ − 519
QVERIFY(r3.isError());
+ − 520
QCOMPARE(r3.toString(), QString::fromLatin1("TypeError: Cannot supply flags when constructing one RegExp from another."));
+ − 521
+ − 522
QScriptValue r4 = rxCtor.call(QScriptValue(), QScriptValueList() << "foo" << "gim");
+ − 523
QVERIFY(r4.isRegExp());
+ − 524
+ − 525
QScriptValue r5 = rxCtor.construct(QScriptValueList() << r);
+ − 526
QVERIFY(r5.isRegExp());
+ − 527
QCOMPARE(r5.toString(), QString::fromLatin1("/foo/gim"));
+ − 528
// In JSC, constructing a RegExp from another produces the same identical object.
+ − 529
// This is different from SpiderMonkey and old back-end.
+ − 530
QVERIFY(r5.strictlyEquals(r));
+ − 531
+ − 532
QScriptValue r6 = rxCtor.construct(QScriptValueList() << "foo" << "bar");
+ − 533
QVERIFY(r6.isError());
+ − 534
QCOMPARE(r6.toString(), QString::fromLatin1("SyntaxError: Invalid regular expression: invalid regular expression flag"));
+ − 535
+ − 536
QScriptValue r7 = eng.evaluate("/foo/gimp");
+ − 537
QVERIFY(r7.isError());
+ − 538
QCOMPARE(r7.toString(), QString::fromLatin1("SyntaxError: Invalid regular expression: invalid regular expression flag"));
+ − 539
+ − 540
QScriptValue r8 = eng.evaluate("/foo/migmigmig");
+ − 541
QVERIFY(r8.isRegExp());
+ − 542
QCOMPARE(r8.toString(), QString::fromLatin1("/foo/gim"));
+ − 543
+ − 544
QScriptValue r9 = rxCtor.construct();
+ − 545
QVERIFY(r9.isRegExp());
+ − 546
QCOMPARE(r9.toString(), QString::fromLatin1("/(?:)/"));
+ − 547
+ − 548
QScriptValue r10 = rxCtor.construct(QScriptValueList() << "" << "gim");
+ − 549
QVERIFY(r10.isRegExp());
+ − 550
QCOMPARE(r10.toString(), QString::fromLatin1("/(?:)/gim"));
+ − 551
+ − 552
QScriptValue r11 = rxCtor.construct(QScriptValueList() << "{1.*}" << "g");
+ − 553
QVERIFY(r11.isRegExp());
+ − 554
QCOMPARE(r11.toString(), QString::fromLatin1("/{1.*}/g"));
+ − 555
}
+ − 556
}
+ − 557
+ − 558
void tst_QScriptEngine::newDate()
+ − 559
{
+ − 560
QScriptEngine eng;
+ − 561
+ − 562
{
+ − 563
QScriptValue date = eng.newDate(0);
+ − 564
QCOMPARE(date.isValid(), true);
+ − 565
QCOMPARE(date.isDate(), true);
+ − 566
QCOMPARE(date.isObject(), true);
+ − 567
QVERIFY(!date.isFunction());
+ − 568
// prototype should be Date.prototype
+ − 569
QCOMPARE(date.prototype().isValid(), true);
+ − 570
QCOMPARE(date.prototype().isDate(), true);
+ − 571
QCOMPARE(date.prototype().strictlyEquals(eng.evaluate("Date.prototype")), true);
+ − 572
}
+ − 573
+ − 574
{
+ − 575
QDateTime dt = QDateTime(QDate(1, 2, 3), QTime(4, 5, 6, 7), Qt::LocalTime);
+ − 576
QScriptValue date = eng.newDate(dt);
+ − 577
QCOMPARE(date.isValid(), true);
+ − 578
QCOMPARE(date.isDate(), true);
+ − 579
QCOMPARE(date.isObject(), true);
+ − 580
// prototype should be Date.prototype
+ − 581
QCOMPARE(date.prototype().isValid(), true);
+ − 582
QCOMPARE(date.prototype().isDate(), true);
+ − 583
QCOMPARE(date.prototype().strictlyEquals(eng.evaluate("Date.prototype")), true);
+ − 584
+ − 585
QCOMPARE(date.toDateTime(), dt);
+ − 586
}
+ − 587
+ − 588
{
+ − 589
QDateTime dt = QDateTime(QDate(1, 2, 3), QTime(4, 5, 6, 7), Qt::UTC);
+ − 590
QScriptValue date = eng.newDate(dt);
+ − 591
// toDateTime() result should be in local time
+ − 592
QCOMPARE(date.toDateTime(), dt.toLocalTime());
+ − 593
}
+ − 594
+ − 595
// Date.parse() should return NaN when it fails
+ − 596
{
+ − 597
QScriptValue ret = eng.evaluate("Date.parse()");
+ − 598
QVERIFY(ret.isNumber());
+ − 599
QVERIFY(qIsNaN(ret.toNumber()));
+ − 600
}
+ − 601
+ − 602
// Date.parse() should be able to parse the output of Date().toString()
+ − 603
#ifndef Q_WS_WIN // TODO: Test and remove this since 169701 has been fixed
+ − 604
{
+ − 605
QScriptValue ret = eng.evaluate("var x = new Date(); var s = x.toString(); s == new Date(Date.parse(s)).toString()");
+ − 606
QVERIFY(ret.isBoolean());
+ − 607
QCOMPARE(ret.toBoolean(), true);
+ − 608
}
+ − 609
#endif
+ − 610
}
+ − 611
+ − 612
void tst_QScriptEngine::newQObject()
+ − 613
{
+ − 614
QScriptEngine eng;
+ − 615
+ − 616
{
+ − 617
QScriptValue qobject = eng.newQObject(0);
+ − 618
QCOMPARE(qobject.isValid(), true);
+ − 619
QCOMPARE(qobject.isNull(), true);
+ − 620
QCOMPARE(qobject.isObject(), false);
+ − 621
QCOMPARE(qobject.toQObject(), (QObject *)0);
+ − 622
}
+ − 623
{
+ − 624
QScriptValue qobject = eng.newQObject(this);
+ − 625
QCOMPARE(qobject.isValid(), true);
+ − 626
QCOMPARE(qobject.isQObject(), true);
+ − 627
QCOMPARE(qobject.isObject(), true);
+ − 628
QCOMPARE(qobject.toQObject(), (QObject *)this);
+ − 629
QVERIFY(!qobject.isFunction());
+ − 630
// prototype should be QObject.prototype
+ − 631
QCOMPARE(qobject.prototype().isValid(), true);
+ − 632
QCOMPARE(qobject.prototype().isQObject(), true);
+ − 633
QCOMPARE(qobject.scriptClass(), (QScriptClass*)0);
+ − 634
}
+ − 635
+ − 636
// test ownership
+ − 637
{
+ − 638
QPointer<QObject> ptr = new QObject();
+ − 639
QVERIFY(ptr != 0);
+ − 640
{
+ − 641
QScriptValue v = eng.newQObject(ptr, QScriptEngine::ScriptOwnership);
+ − 642
}
+ − 643
eng.evaluate("gc()");
+ − 644
if (ptr)
+ − 645
QEXPECT_FAIL("", "In the JSC-based back-end, script-owned QObjects are not always deleted immediately during GC", Continue);
+ − 646
QVERIFY(ptr == 0);
+ − 647
}
+ − 648
{
+ − 649
QPointer<QObject> ptr = new QObject();
+ − 650
QVERIFY(ptr != 0);
+ − 651
{
+ − 652
QScriptValue v = eng.newQObject(ptr, QScriptEngine::QtOwnership);
+ − 653
}
+ − 654
QObject *before = ptr;
+ − 655
eng.evaluate("gc()");
+ − 656
QVERIFY(ptr == before);
+ − 657
delete ptr;
+ − 658
}
+ − 659
{
+ − 660
QObject *parent = new QObject();
+ − 661
QObject *child = new QObject(parent);
+ − 662
QScriptValue v = eng.newQObject(child, QScriptEngine::QtOwnership);
+ − 663
QCOMPARE(v.toQObject(), child);
+ − 664
delete parent;
+ − 665
QCOMPARE(v.toQObject(), (QObject *)0);
+ − 666
}
+ − 667
{
+ − 668
QPointer<QObject> ptr = new QObject();
+ − 669
QVERIFY(ptr != 0);
+ − 670
{
+ − 671
QScriptValue v = eng.newQObject(ptr, QScriptEngine::AutoOwnership);
+ − 672
}
+ − 673
eng.evaluate("gc()");
+ − 674
// no parent, so it should be like ScriptOwnership
+ − 675
if (ptr)
+ − 676
QEXPECT_FAIL("", "In the JSC-based back-end, script-owned QObjects are not always deleted immediately during GC", Continue);
+ − 677
QVERIFY(ptr == 0);
+ − 678
}
+ − 679
{
+ − 680
QObject *parent = new QObject();
+ − 681
QPointer<QObject> child = new QObject(parent);
+ − 682
QVERIFY(child != 0);
+ − 683
{
+ − 684
QScriptValue v = eng.newQObject(child, QScriptEngine::AutoOwnership);
+ − 685
}
+ − 686
eng.evaluate("gc()");
+ − 687
// has parent, so it should be like QtOwnership
+ − 688
QVERIFY(child != 0);
+ − 689
delete parent;
+ − 690
}
+ − 691
+ − 692
// "promote" plain object to QObject
+ − 693
{
+ − 694
QScriptValue obj = eng.newObject();
+ − 695
QScriptValue originalProto = obj.prototype();
+ − 696
QScriptValue ret = eng.newQObject(obj, this);
+ − 697
QVERIFY(ret.isValid());
+ − 698
QVERIFY(ret.isQObject());
+ − 699
QVERIFY(ret.strictlyEquals(obj));
+ − 700
QVERIFY(obj.isQObject());
+ − 701
QCOMPARE(ret.toQObject(), (QObject *)this);
+ − 702
QVERIFY(ret.prototype().strictlyEquals(originalProto));
+ − 703
QScriptValue val = ret.property("objectName");
+ − 704
QVERIFY(val.isString());
+ − 705
}
+ − 706
// "promote" variant object to QObject
+ − 707
{
+ − 708
QScriptValue obj = eng.newVariant(123);
+ − 709
QVERIFY(obj.isVariant());
+ − 710
QScriptValue originalProto = obj.prototype();
+ − 711
QScriptValue ret = eng.newQObject(obj, this);
+ − 712
QVERIFY(ret.isQObject());
+ − 713
QVERIFY(ret.strictlyEquals(obj));
+ − 714
QVERIFY(obj.isQObject());
+ − 715
QCOMPARE(ret.toQObject(), (QObject *)this);
+ − 716
QVERIFY(ret.prototype().strictlyEquals(originalProto));
+ − 717
}
+ − 718
// replace QObject* of existing object
+ − 719
{
+ − 720
QScriptValue object = eng.newVariant(123);
+ − 721
QScriptValue originalProto = object.prototype();
+ − 722
QObject otherQObject;
+ − 723
QScriptValue ret = eng.newQObject(object, &otherQObject);
+ − 724
QVERIFY(ret.isValid());
+ − 725
QVERIFY(ret.isQObject());
+ − 726
QVERIFY(ret.strictlyEquals(object));
+ − 727
QCOMPARE(ret.toQObject(), (QObject *)&otherQObject);
+ − 728
QVERIFY(ret.prototype().strictlyEquals(originalProto));
+ − 729
}
+ − 730
+ − 731
// calling newQObject() several times with same object
+ − 732
for (int x = 0; x < 2; ++x) {
+ − 733
QObject qobj;
+ − 734
// the default is to create a new wrapper object
+ − 735
QScriptValue obj1 = eng.newQObject(&qobj);
+ − 736
QScriptValue obj2 = eng.newQObject(&qobj);
+ − 737
QVERIFY(!obj2.strictlyEquals(obj1));
+ − 738
+ − 739
QScriptEngine::QObjectWrapOptions opt = 0;
+ − 740
bool preferExisting = (x != 0);
+ − 741
if (preferExisting)
+ − 742
opt |= QScriptEngine::PreferExistingWrapperObject;
+ − 743
+ − 744
QScriptValue obj3 = eng.newQObject(&qobj, QScriptEngine::AutoOwnership, opt);
+ − 745
QVERIFY(!obj3.strictlyEquals(obj2));
+ − 746
QScriptValue obj4 = eng.newQObject(&qobj, QScriptEngine::AutoOwnership, opt);
+ − 747
QCOMPARE(obj4.strictlyEquals(obj3), preferExisting);
+ − 748
+ − 749
QScriptValue obj5 = eng.newQObject(&qobj, QScriptEngine::ScriptOwnership, opt);
+ − 750
QVERIFY(!obj5.strictlyEquals(obj4));
+ − 751
QScriptValue obj6 = eng.newQObject(&qobj, QScriptEngine::ScriptOwnership, opt);
+ − 752
QCOMPARE(obj6.strictlyEquals(obj5), preferExisting);
+ − 753
+ − 754
QScriptValue obj7 = eng.newQObject(&qobj, QScriptEngine::ScriptOwnership,
+ − 755
QScriptEngine::ExcludeSuperClassMethods | opt);
+ − 756
QVERIFY(!obj7.strictlyEquals(obj6));
+ − 757
QScriptValue obj8 = eng.newQObject(&qobj, QScriptEngine::ScriptOwnership,
+ − 758
QScriptEngine::ExcludeSuperClassMethods | opt);
+ − 759
QCOMPARE(obj8.strictlyEquals(obj7), preferExisting);
+ − 760
}
+ − 761
+ − 762
// newQObject() should set the default prototype, if one has been registered
+ − 763
{
+ − 764
QScriptValue oldQObjectProto = eng.defaultPrototype(qMetaTypeId<QObject*>());
+ − 765
+ − 766
QScriptValue qobjectProto = eng.newObject();
+ − 767
eng.setDefaultPrototype(qMetaTypeId<QObject*>(), qobjectProto);
+ − 768
{
+ − 769
QScriptValue ret = eng.newQObject(this);
+ − 770
QVERIFY(ret.prototype().equals(qobjectProto));
+ − 771
}
+ − 772
QScriptValue tstProto = eng.newObject();
+ − 773
int typeId = qRegisterMetaType<tst_QScriptEngine*>("tst_QScriptEngine*");
+ − 774
eng.setDefaultPrototype(typeId, tstProto);
+ − 775
{
+ − 776
QScriptValue ret = eng.newQObject(this);
+ − 777
QVERIFY(ret.prototype().equals(tstProto));
+ − 778
}
+ − 779
+ − 780
eng.setDefaultPrototype(qMetaTypeId<QObject*>(), oldQObjectProto);
+ − 781
eng.setDefaultPrototype(typeId, QScriptValue());
+ − 782
}
+ − 783
}
+ − 784
+ − 785
QT_BEGIN_NAMESPACE
+ − 786
Q_SCRIPT_DECLARE_QMETAOBJECT(QObject, QObject*)
+ − 787
Q_SCRIPT_DECLARE_QMETAOBJECT(QWidget, QWidget*)
+ − 788
QT_END_NAMESPACE
+ − 789
+ − 790
static QScriptValue myConstructor(QScriptContext *ctx, QScriptEngine *eng)
+ − 791
{
+ − 792
QScriptValue obj;
+ − 793
if (ctx->isCalledAsConstructor()) {
+ − 794
obj = ctx->thisObject();
+ − 795
} else {
+ − 796
obj = eng->newObject();
+ − 797
obj.setPrototype(ctx->callee().property("prototype"));
+ − 798
}
+ − 799
obj.setProperty("isCalledAsConstructor", QScriptValue(eng, ctx->isCalledAsConstructor()));
+ − 800
return obj;
+ − 801
}
+ − 802
14
+ − 803
static QScriptValue instanceofJS(const QScriptValue &inst, const QScriptValue &ctor)
+ − 804
{
+ − 805
return inst.engine()->evaluate("(function(inst, ctor) { return inst instanceof ctor; })")
+ − 806
.call(QScriptValue(), QScriptValueList() << inst << ctor);
+ − 807
}
+ − 808
0
+ − 809
void tst_QScriptEngine::newQMetaObject()
+ − 810
{
+ − 811
QScriptEngine eng;
+ − 812
#if 0
+ − 813
QScriptValue qclass = eng.newQMetaObject<QObject>();
+ − 814
QScriptValue qclass2 = eng.newQMetaObject<QWidget>();
+ − 815
#else
+ − 816
QScriptValue qclass = qScriptValueFromQMetaObject<QObject>(&eng);
+ − 817
QScriptValue qclass2 = qScriptValueFromQMetaObject<QWidget>(&eng);
+ − 818
#endif
+ − 819
QCOMPARE(qclass.isValid(), true);
+ − 820
QCOMPARE(qclass.isQMetaObject(), true);
+ − 821
QCOMPARE(qclass.toQMetaObject(), &QObject::staticMetaObject);
+ − 822
QCOMPARE(qclass.isFunction(), true);
+ − 823
QVERIFY(qclass.property("prototype").isObject());
+ − 824
+ − 825
QCOMPARE(qclass2.isValid(), true);
+ − 826
QCOMPARE(qclass2.isQMetaObject(), true);
+ − 827
QCOMPARE(qclass2.toQMetaObject(), &QWidget::staticMetaObject);
+ − 828
QCOMPARE(qclass2.isFunction(), true);
+ − 829
QVERIFY(qclass2.property("prototype").isObject());
+ − 830
+ − 831
// prototype should be QMetaObject.prototype
+ − 832
QCOMPARE(qclass.prototype().isObject(), true);
+ − 833
QCOMPARE(qclass2.prototype().isObject(), true);
+ − 834
+ − 835
QScriptValue instance = qclass.construct();
+ − 836
QCOMPARE(instance.isQObject(), true);
+ − 837
QCOMPARE(instance.toQObject()->metaObject(), qclass.toQMetaObject());
+ − 838
QVERIFY(instance.instanceOf(qclass));
14
+ − 839
QVERIFY(instanceofJS(instance, qclass).strictlyEquals(true));
0
+ − 840
+ − 841
QScriptValue instance2 = qclass2.construct();
+ − 842
QCOMPARE(instance2.isQObject(), true);
+ − 843
QCOMPARE(instance2.toQObject()->metaObject(), qclass2.toQMetaObject());
+ − 844
QVERIFY(instance2.instanceOf(qclass2));
14
+ − 845
QVERIFY(instanceofJS(instance2, qclass2).strictlyEquals(true));
+ − 846
QVERIFY(!instance2.instanceOf(qclass));
+ − 847
QVERIFY(instanceofJS(instance2, qclass).strictlyEquals(false));
0
+ − 848
+ − 849
QScriptValueList args;
+ − 850
args << instance;
+ − 851
QScriptValue instance3 = qclass.construct(args);
+ − 852
QCOMPARE(instance3.isQObject(), true);
+ − 853
QCOMPARE(instance3.toQObject()->parent(), instance.toQObject());
+ − 854
QVERIFY(instance3.instanceOf(qclass));
14
+ − 855
QVERIFY(instanceofJS(instance3, qclass).strictlyEquals(true));
+ − 856
QVERIFY(!instance3.instanceOf(qclass2));
+ − 857
QVERIFY(instanceofJS(instance3, qclass2).strictlyEquals(false));
0
+ − 858
args.clear();
+ − 859
+ − 860
QPointer<QObject> qpointer1 = instance.toQObject();
+ − 861
QPointer<QObject> qpointer2 = instance2.toQObject();
+ − 862
QPointer<QObject> qpointer3 = instance3.toQObject();
+ − 863
+ − 864
QVERIFY(qpointer1);
+ − 865
QVERIFY(qpointer2);
+ − 866
QVERIFY(qpointer3);
+ − 867
+ − 868
// verify that AutoOwnership is in effect
+ − 869
instance = QScriptValue();
+ − 870
collectGarbage_helper(eng);
+ − 871
+ − 872
QVERIFY(!qpointer1);
+ − 873
QVERIFY(qpointer2);
+ − 874
QVERIFY(!qpointer3); // was child of instance
+ − 875
+ − 876
QVERIFY(instance.toQObject() == 0);
+ − 877
QVERIFY(instance3.toQObject() == 0); // was child of instance
+ − 878
QVERIFY(instance2.toQObject() != 0);
+ − 879
instance2 = QScriptValue();
+ − 880
collectGarbage_helper(eng);
+ − 881
QVERIFY(instance2.toQObject() == 0);
+ − 882
+ − 883
// with custom constructor
+ − 884
QScriptValue ctor = eng.newFunction(myConstructor);
+ − 885
QScriptValue qclass3 = eng.newQMetaObject(&QObject::staticMetaObject, ctor);
+ − 886
QVERIFY(qclass3.property("prototype").equals(ctor.property("prototype")));
+ − 887
{
+ − 888
QScriptValue ret = qclass3.call();
+ − 889
QVERIFY(ret.isObject());
+ − 890
QVERIFY(ret.property("isCalledAsConstructor").isBoolean());
+ − 891
QVERIFY(!ret.property("isCalledAsConstructor").toBoolean());
+ − 892
QVERIFY(ret.instanceOf(qclass3));
14
+ − 893
QVERIFY(instanceofJS(ret, qclass3).strictlyEquals(true));
+ − 894
QVERIFY(!ret.instanceOf(qclass));
+ − 895
QVERIFY(instanceofJS(ret, qclass).strictlyEquals(false));
0
+ − 896
}
+ − 897
{
+ − 898
QScriptValue ret = qclass3.construct();
+ − 899
QVERIFY(ret.isObject());
+ − 900
QVERIFY(ret.property("isCalledAsConstructor").isBoolean());
+ − 901
QVERIFY(ret.property("isCalledAsConstructor").toBoolean());
+ − 902
QVERIFY(ret.instanceOf(qclass3));
14
+ − 903
QVERIFY(instanceofJS(ret, qclass3).strictlyEquals(true));
+ − 904
QVERIFY(!ret.instanceOf(qclass2));
+ − 905
QVERIFY(instanceofJS(ret, qclass2).strictlyEquals(false));
0
+ − 906
}
+ − 907
+ − 908
// subclassing
+ − 909
qclass2.setProperty("prototype", qclass.construct());
+ − 910
QVERIFY(qclass2.construct().instanceOf(qclass));
14
+ − 911
QVERIFY(instanceofJS(qclass2.construct(), qclass).strictlyEquals(true));
0
+ − 912
+ − 913
// with meta-constructor
+ − 914
QScriptValue qclass4 = eng.newQMetaObject(&QObject::staticMetaObject);
+ − 915
{
+ − 916
QScriptValue inst = qclass4.construct();
+ − 917
QVERIFY(inst.isQObject());
+ − 918
QVERIFY(inst.toQObject() != 0);
+ − 919
QCOMPARE(inst.toQObject()->parent(), (QObject*)0);
+ − 920
QVERIFY(inst.instanceOf(qclass4));
14
+ − 921
QVERIFY(instanceofJS(inst, qclass4).strictlyEquals(true));
+ − 922
QVERIFY(!inst.instanceOf(qclass3));
+ − 923
QVERIFY(instanceofJS(inst, qclass3).strictlyEquals(false));
0
+ − 924
}
+ − 925
{
+ − 926
QScriptValue inst = qclass4.construct(QScriptValueList() << eng.newQObject(this));
+ − 927
QVERIFY(inst.isQObject());
+ − 928
QVERIFY(inst.toQObject() != 0);
+ − 929
QCOMPARE(inst.toQObject()->parent(), (QObject*)this);
+ − 930
QVERIFY(inst.instanceOf(qclass4));
14
+ − 931
QVERIFY(instanceofJS(inst, qclass4).strictlyEquals(true));
+ − 932
QVERIFY(!inst.instanceOf(qclass2));
+ − 933
QVERIFY(instanceofJS(inst, qclass2).strictlyEquals(false));
0
+ − 934
}
+ − 935
}
+ − 936
+ − 937
void tst_QScriptEngine::newActivationObject()
+ − 938
{
+ − 939
QSKIP("internal function not implemented in JSC-based back-end", SkipAll);
+ − 940
QScriptEngine eng;
+ − 941
QScriptValue act = eng.newActivationObject();
+ − 942
QEXPECT_FAIL("", "", Continue);
+ − 943
QCOMPARE(act.isValid(), true);
+ − 944
QEXPECT_FAIL("", "", Continue);
+ − 945
QCOMPARE(act.isObject(), true);
+ − 946
QVERIFY(!act.isFunction());
+ − 947
QScriptValue v(&eng, 123);
+ − 948
act.setProperty("prop", v);
+ − 949
QEXPECT_FAIL("", "", Continue);
+ − 950
QCOMPARE(act.property("prop").strictlyEquals(v), true);
+ − 951
QCOMPARE(act.scope().isValid(), false);
+ − 952
QEXPECT_FAIL("", "", Continue);
+ − 953
QVERIFY(act.prototype().isNull());
+ − 954
}
+ − 955
+ − 956
void tst_QScriptEngine::getSetGlobalObject()
+ − 957
{
+ − 958
QScriptEngine eng;
+ − 959
QScriptValue glob = eng.globalObject();
+ − 960
QCOMPARE(glob.isValid(), true);
+ − 961
QCOMPARE(glob.isObject(), true);
+ − 962
QVERIFY(!glob.isFunction());
+ − 963
QVERIFY(eng.currentContext()->thisObject().strictlyEquals(glob));
+ − 964
QVERIFY(eng.currentContext()->activationObject().strictlyEquals(glob));
+ − 965
QCOMPARE(glob.toString(), QString::fromLatin1("[object global]"));
+ − 966
// prototype should be Object.prototype
+ − 967
QCOMPARE(glob.prototype().isValid(), true);
+ − 968
QCOMPARE(glob.prototype().isObject(), true);
+ − 969
QCOMPARE(glob.prototype().strictlyEquals(eng.evaluate("Object.prototype")), true);
+ − 970
+ − 971
QScriptValue obj = eng.newObject();
+ − 972
eng.setGlobalObject(obj);
+ − 973
QVERIFY(eng.globalObject().strictlyEquals(obj));
+ − 974
QVERIFY(eng.currentContext()->thisObject().strictlyEquals(obj));
+ − 975
QVERIFY(eng.currentContext()->activationObject().strictlyEquals(obj));
+ − 976
QVERIFY(eng.evaluate("this").strictlyEquals(obj));
+ − 977
QCOMPARE(eng.globalObject().toString(), QString::fromLatin1("[object Object]"));
+ − 978
+ − 979
glob = QScriptValue(); // kill reference to old global object
+ − 980
collectGarbage_helper(eng);
+ − 981
obj = eng.newObject();
+ − 982
eng.setGlobalObject(obj);
+ − 983
QVERIFY(eng.globalObject().strictlyEquals(obj));
+ − 984
QVERIFY(eng.currentContext()->thisObject().strictlyEquals(obj));
+ − 985
QVERIFY(eng.currentContext()->activationObject().strictlyEquals(obj));
+ − 986
+ − 987
collectGarbage_helper(eng);
+ − 988
QVERIFY(eng.globalObject().strictlyEquals(obj));
+ − 989
QVERIFY(eng.currentContext()->thisObject().strictlyEquals(obj));
+ − 990
QVERIFY(eng.currentContext()->activationObject().strictlyEquals(obj));
+ − 991
+ − 992
QVERIFY(!obj.property("foo").isValid());
+ − 993
eng.evaluate("var foo = 123");
+ − 994
{
+ − 995
QScriptValue ret = obj.property("foo");
+ − 996
QVERIFY(ret.isNumber());
+ − 997
QCOMPARE(ret.toInt32(), 123);
+ − 998
}
+ − 999
+ − 1000
QVERIFY(!obj.property("bar").isValid());
+ − 1001
eng.evaluate("bar = 456");
+ − 1002
{
+ − 1003
QScriptValue ret = obj.property("bar");
+ − 1004
QVERIFY(ret.isNumber());
+ − 1005
QCOMPARE(ret.toInt32(), 456);
+ − 1006
}
+ − 1007
+ − 1008
QVERIFY(!obj.property("baz").isValid());
+ − 1009
eng.evaluate("this['baz'] = 789");
+ − 1010
{
+ − 1011
QScriptValue ret = obj.property("baz");
+ − 1012
QVERIFY(ret.isNumber());
+ − 1013
QCOMPARE(ret.toInt32(), 789);
+ − 1014
}
+ − 1015
+ − 1016
{
+ − 1017
QScriptValue ret = eng.evaluate("(function() { return this; })()");
+ − 1018
QVERIFY(ret.strictlyEquals(obj));
+ − 1019
}
+ − 1020
}
+ − 1021
+ − 1022
static QScriptValue getSetFoo(QScriptContext *ctx, QScriptEngine *)
+ − 1023
{
+ − 1024
if (ctx->argumentCount() > 0)
+ − 1025
ctx->thisObject().setProperty("foo", ctx->argument(0));
+ − 1026
return ctx->thisObject().property("foo");
+ − 1027
}
+ − 1028
+ − 1029
void tst_QScriptEngine::globalObjectProperties()
+ − 1030
{
+ − 1031
QScriptEngine eng;
+ − 1032
QScriptValue global = eng.globalObject();
+ − 1033
+ − 1034
QVERIFY(global.property("NaN").isNumber());
+ − 1035
QVERIFY(qIsNaN(global.property("NaN").toNumber()));
+ − 1036
QCOMPARE(global.propertyFlags("NaN"), QScriptValue::SkipInEnumeration | QScriptValue::Undeletable);
+ − 1037
+ − 1038
QVERIFY(global.property("Infinity").isNumber());
+ − 1039
QVERIFY(qIsInf(global.property("Infinity").toNumber()));
+ − 1040
QCOMPARE(global.propertyFlags("NaN"), QScriptValue::SkipInEnumeration | QScriptValue::Undeletable);
+ − 1041
+ − 1042
QVERIFY(global.property("undefined").isUndefined());
+ − 1043
QCOMPARE(global.propertyFlags("undefined"), QScriptValue::SkipInEnumeration | QScriptValue::Undeletable);
+ − 1044
+ − 1045
QVERIFY(global.property("eval").isFunction());
+ − 1046
QCOMPARE(global.propertyFlags("eval"), QScriptValue::SkipInEnumeration);
+ − 1047
+ − 1048
QVERIFY(global.property("parseInt").isFunction());
+ − 1049
QCOMPARE(global.propertyFlags("parseInt"), QScriptValue::SkipInEnumeration);
+ − 1050
+ − 1051
QVERIFY(global.property("parseFloat").isFunction());
+ − 1052
QCOMPARE(global.propertyFlags("parseFloat"), QScriptValue::SkipInEnumeration);
+ − 1053
+ − 1054
QVERIFY(global.property("isNaN").isFunction());
+ − 1055
QCOMPARE(global.propertyFlags("isNaN"), QScriptValue::SkipInEnumeration);
+ − 1056
+ − 1057
QVERIFY(global.property("isFinite").isFunction());
+ − 1058
QCOMPARE(global.propertyFlags("isFinite"), QScriptValue::SkipInEnumeration);
+ − 1059
+ − 1060
QVERIFY(global.property("decodeURI").isFunction());
+ − 1061
QCOMPARE(global.propertyFlags("decodeURI"), QScriptValue::SkipInEnumeration);
+ − 1062
+ − 1063
QVERIFY(global.property("decodeURIComponent").isFunction());
+ − 1064
QCOMPARE(global.propertyFlags("decodeURIComponent"), QScriptValue::SkipInEnumeration);
+ − 1065
+ − 1066
QVERIFY(global.property("encodeURI").isFunction());
+ − 1067
QCOMPARE(global.propertyFlags("encodeURI"), QScriptValue::SkipInEnumeration);
+ − 1068
+ − 1069
QVERIFY(global.property("encodeURIComponent").isFunction());
+ − 1070
QCOMPARE(global.propertyFlags("encodeURIComponent"), QScriptValue::SkipInEnumeration);
+ − 1071
+ − 1072
QVERIFY(global.property("Object").isFunction());
+ − 1073
QCOMPARE(global.propertyFlags("Object"), QScriptValue::SkipInEnumeration);
+ − 1074
QVERIFY(global.property("Function").isFunction());
+ − 1075
QCOMPARE(global.propertyFlags("Function"), QScriptValue::SkipInEnumeration);
+ − 1076
QVERIFY(global.property("Array").isFunction());
+ − 1077
QCOMPARE(global.propertyFlags("Array"), QScriptValue::SkipInEnumeration);
+ − 1078
QVERIFY(global.property("String").isFunction());
+ − 1079
QCOMPARE(global.propertyFlags("String"), QScriptValue::SkipInEnumeration);
+ − 1080
QVERIFY(global.property("Boolean").isFunction());
+ − 1081
QCOMPARE(global.propertyFlags("Boolean"), QScriptValue::SkipInEnumeration);
+ − 1082
QVERIFY(global.property("Number").isFunction());
+ − 1083
QCOMPARE(global.propertyFlags("Number"), QScriptValue::SkipInEnumeration);
+ − 1084
QVERIFY(global.property("Date").isFunction());
+ − 1085
QCOMPARE(global.propertyFlags("Date"), QScriptValue::SkipInEnumeration);
+ − 1086
QVERIFY(global.property("RegExp").isFunction());
+ − 1087
QCOMPARE(global.propertyFlags("RegExp"), QScriptValue::SkipInEnumeration);
+ − 1088
QVERIFY(global.property("Error").isFunction());
+ − 1089
QCOMPARE(global.propertyFlags("Error"), QScriptValue::SkipInEnumeration);
+ − 1090
QVERIFY(global.property("EvalError").isFunction());
+ − 1091
QCOMPARE(global.propertyFlags("EvalError"), QScriptValue::SkipInEnumeration);
+ − 1092
QVERIFY(global.property("RangeError").isFunction());
+ − 1093
QCOMPARE(global.propertyFlags("RangeError"), QScriptValue::SkipInEnumeration);
+ − 1094
QVERIFY(global.property("ReferenceError").isFunction());
+ − 1095
QCOMPARE(global.propertyFlags("ReferenceError"), QScriptValue::SkipInEnumeration);
+ − 1096
QVERIFY(global.property("SyntaxError").isFunction());
+ − 1097
QCOMPARE(global.propertyFlags("SyntaxError"), QScriptValue::SkipInEnumeration);
+ − 1098
QVERIFY(global.property("TypeError").isFunction());
+ − 1099
QCOMPARE(global.propertyFlags("TypeError"), QScriptValue::SkipInEnumeration);
+ − 1100
QVERIFY(global.property("URIError").isFunction());
+ − 1101
QCOMPARE(global.propertyFlags("URIError"), QScriptValue::SkipInEnumeration);
+ − 1102
QVERIFY(global.property("Math").isObject());
+ − 1103
QVERIFY(!global.property("Math").isFunction());
+ − 1104
QEXPECT_FAIL("", "[ECMA compliance] JSC sets DontDelete flag for Math object", Continue);
+ − 1105
QCOMPARE(global.propertyFlags("Math"), QScriptValue::SkipInEnumeration);
+ − 1106
+ − 1107
// enumeration
+ − 1108
QSet<QString> expectedNames;
+ − 1109
expectedNames
+ − 1110
<< "isNaN"
+ − 1111
<< "parseFloat"
+ − 1112
<< "String"
+ − 1113
<< "EvalError"
+ − 1114
<< "URIError"
+ − 1115
<< "Math"
+ − 1116
<< "encodeURIComponent"
+ − 1117
<< "RangeError"
+ − 1118
<< "eval"
+ − 1119
<< "isFinite"
+ − 1120
<< "ReferenceError"
+ − 1121
<< "Infinity"
+ − 1122
<< "Function"
+ − 1123
<< "RegExp"
+ − 1124
<< "Number"
+ − 1125
<< "parseInt"
+ − 1126
<< "Object"
+ − 1127
<< "decodeURI"
+ − 1128
<< "TypeError"
+ − 1129
<< "Boolean"
+ − 1130
<< "encodeURI"
+ − 1131
<< "NaN"
+ − 1132
<< "Error"
+ − 1133
<< "decodeURIComponent"
+ − 1134
<< "Date"
+ − 1135
<< "Array"
+ − 1136
<< "escape"
+ − 1137
<< "unescape"
+ − 1138
<< "SyntaxError"
+ − 1139
<< "undefined"
+ − 1140
// non-standard
+ − 1141
<< "gc"
+ − 1142
<< "version"
+ − 1143
<< "print"
+ − 1144
// JavaScriptCore
+ − 1145
<< "JSON"
+ − 1146
;
+ − 1147
QSet<QString> actualNames;
+ − 1148
{
+ − 1149
QScriptValueIterator it(global);
+ − 1150
while (it.hasNext()) {
+ − 1151
it.next();
+ − 1152
actualNames.insert(it.name());
+ − 1153
}
+ − 1154
}
+ − 1155
+ − 1156
QSet<QString> remainingNames = actualNames;
+ − 1157
{
+ − 1158
QSet<QString>::const_iterator it;
+ − 1159
for (it = expectedNames.constBegin(); it != expectedNames.constEnd(); ++it) {
+ − 1160
QString name = *it;
+ − 1161
QVERIFY(actualNames.contains(name));
+ − 1162
remainingNames.remove(name);
+ − 1163
}
+ − 1164
}
+ − 1165
QVERIFY(remainingNames.isEmpty());
+ − 1166
+ − 1167
// create property with no attributes
+ − 1168
{
+ − 1169
QString name = QString::fromLatin1("foo");
+ − 1170
QVERIFY(!global.property(name).isValid());
+ − 1171
QScriptValue val(123);
+ − 1172
global.setProperty(name, val);
+ − 1173
QVERIFY(global.property(name).equals(val));
+ − 1174
QVERIFY(global.propertyFlags(name) == 0);
+ − 1175
global.setProperty(name, QScriptValue());
+ − 1176
QVERIFY(!global.property(name).isValid());
+ − 1177
}
+ − 1178
// create property with attributes
+ − 1179
{
+ − 1180
QString name = QString::fromLatin1("bar");
+ − 1181
QVERIFY(!global.property(name).isValid());
+ − 1182
QScriptValue val(QString::fromLatin1("ciao"));
+ − 1183
QScriptValue::PropertyFlags flags = QScriptValue::ReadOnly | QScriptValue::SkipInEnumeration;
+ − 1184
global.setProperty(name, val, flags);
+ − 1185
QVERIFY(global.property(name).equals(val));
3
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 1186
QEXPECT_FAIL("", "QTBUG-6134: custom Global Object properties don't retain attributes", Continue);
0
+ − 1187
QCOMPARE(global.propertyFlags(name), flags);
+ − 1188
global.setProperty(name, QScriptValue());
+ − 1189
QVERIFY(!global.property(name).isValid());
+ − 1190
}
+ − 1191
}
+ − 1192
+ − 1193
void tst_QScriptEngine::globalObjectGetterSetterProperty()
+ − 1194
{
+ − 1195
QScriptEngine engine;
+ − 1196
QScriptValue global = engine.globalObject();
+ − 1197
global.setProperty("bar", engine.newFunction(getSetFoo),
+ − 1198
QScriptValue::PropertySetter | QScriptValue::PropertyGetter);
+ − 1199
global.setProperty("foo", 123);
+ − 1200
QVERIFY(global.property("bar").equals(global.property("foo")));
+ − 1201
QVERIFY(engine.evaluate("bar").equals(global.property("foo")));
+ − 1202
global.setProperty("bar", 456);
+ − 1203
QVERIFY(global.property("bar").equals(global.property("foo")));
+ − 1204
+ − 1205
engine.evaluate("__defineGetter__('baz', function() { return 789; })");
+ − 1206
QVERIFY(engine.evaluate("baz").equals(789));
+ − 1207
QVERIFY(global.property("baz").equals(789));
+ − 1208
}
+ − 1209
14
+ − 1210
void tst_QScriptEngine::customGlobalObjectWithPrototype()
+ − 1211
{
+ − 1212
for (int x = 0; x < 2; ++x) {
+ − 1213
QScriptEngine engine;
+ − 1214
QScriptValue wrap = engine.newObject();
+ − 1215
QScriptValue global = engine.globalObject();
+ − 1216
QScriptValue originalGlobalProto = global.prototype();
+ − 1217
if (!x) {
+ − 1218
// Set prototype before setting global object
+ − 1219
wrap.setPrototype(global);
+ − 1220
QVERIFY(wrap.prototype().strictlyEquals(global));
+ − 1221
engine.setGlobalObject(wrap);
+ − 1222
} else {
+ − 1223
// Set prototype after setting global object
+ − 1224
engine.setGlobalObject(wrap);
+ − 1225
wrap.setPrototype(global);
+ − 1226
QVERIFY(wrap.prototype().strictlyEquals(global));
+ − 1227
}
+ − 1228
{
+ − 1229
QScriptValue ret = engine.evaluate("print");
+ − 1230
QVERIFY(ret.isFunction());
+ − 1231
QVERIFY(ret.strictlyEquals(wrap.property("print")));
+ − 1232
}
+ − 1233
{
+ − 1234
QScriptValue ret = engine.evaluate("this.print");
+ − 1235
QVERIFY(ret.isFunction());
+ − 1236
QVERIFY(ret.strictlyEquals(wrap.property("print")));
+ − 1237
}
+ − 1238
{
+ − 1239
QScriptValue ret = engine.evaluate("hasOwnProperty('print')");
+ − 1240
QVERIFY(ret.isBool());
+ − 1241
QVERIFY(!ret.toBool());
+ − 1242
}
+ − 1243
{
+ − 1244
QScriptValue ret = engine.evaluate("this.hasOwnProperty('print')");
+ − 1245
QVERIFY(ret.isBool());
+ − 1246
QVERIFY(!ret.toBool());
+ − 1247
}
+ − 1248
+ − 1249
QScriptValue anotherProto = engine.newObject();
+ − 1250
anotherProto.setProperty("anotherProtoProperty", 123);
+ − 1251
global.setPrototype(anotherProto);
+ − 1252
{
+ − 1253
QScriptValue ret = engine.evaluate("print");
+ − 1254
QVERIFY(ret.isFunction());
+ − 1255
QVERIFY(ret.strictlyEquals(wrap.property("print")));
+ − 1256
}
+ − 1257
{
+ − 1258
QScriptValue ret = engine.evaluate("anotherProtoProperty");
+ − 1259
QVERIFY(ret.isNumber());
+ − 1260
QVERIFY(ret.strictlyEquals(wrap.property("anotherProtoProperty")));
+ − 1261
}
+ − 1262
{
+ − 1263
QScriptValue ret = engine.evaluate("this.anotherProtoProperty");
+ − 1264
QVERIFY(ret.isNumber());
+ − 1265
QVERIFY(ret.strictlyEquals(wrap.property("anotherProtoProperty")));
+ − 1266
}
+ − 1267
+ − 1268
wrap.setPrototype(anotherProto);
+ − 1269
{
+ − 1270
QScriptValue ret = engine.evaluate("print");
+ − 1271
QVERIFY(ret.isError());
+ − 1272
QCOMPARE(ret.toString(), QString::fromLatin1("ReferenceError: Can't find variable: print"));
+ − 1273
}
+ − 1274
{
+ − 1275
QScriptValue ret = engine.evaluate("anotherProtoProperty");
+ − 1276
QVERIFY(ret.isNumber());
+ − 1277
QVERIFY(ret.strictlyEquals(wrap.property("anotherProtoProperty")));
+ − 1278
}
+ − 1279
QVERIFY(global.prototype().strictlyEquals(anotherProto));
+ − 1280
+ − 1281
global.setPrototype(originalGlobalProto);
+ − 1282
engine.setGlobalObject(global);
+ − 1283
{
+ − 1284
QScriptValue ret = engine.evaluate("anotherProtoProperty");
+ − 1285
QVERIFY(ret.isError());
+ − 1286
QCOMPARE(ret.toString(), QString::fromLatin1("ReferenceError: Can't find variable: anotherProtoProperty"));
+ − 1287
}
+ − 1288
{
+ − 1289
QScriptValue ret = engine.evaluate("print");
+ − 1290
QVERIFY(ret.isFunction());
+ − 1291
QVERIFY(ret.strictlyEquals(global.property("print")));
+ − 1292
}
+ − 1293
QVERIFY(!anotherProto.property("print").isValid());
+ − 1294
}
+ − 1295
}
+ − 1296
+ − 1297
void tst_QScriptEngine::globalObjectWithCustomPrototype()
+ − 1298
{
+ − 1299
QScriptEngine engine;
+ − 1300
QScriptValue proto = engine.newObject();
+ − 1301
proto.setProperty("protoProperty", 123);
+ − 1302
QScriptValue global = engine.globalObject();
+ − 1303
QScriptValue originalProto = global.prototype();
+ − 1304
global.setPrototype(proto);
+ − 1305
{
+ − 1306
QScriptValue ret = engine.evaluate("protoProperty");
+ − 1307
QVERIFY(ret.isNumber());
+ − 1308
QVERIFY(ret.strictlyEquals(global.property("protoProperty")));
+ − 1309
}
+ − 1310
{
+ − 1311
QScriptValue ret = engine.evaluate("this.protoProperty");
+ − 1312
QVERIFY(ret.isNumber());
+ − 1313
QVERIFY(ret.strictlyEquals(global.property("protoProperty")));
+ − 1314
}
+ − 1315
{
+ − 1316
QScriptValue ret = engine.evaluate("hasOwnProperty('protoProperty')");
+ − 1317
QVERIFY(ret.isBool());
+ − 1318
QVERIFY(!ret.toBool());
+ − 1319
}
+ − 1320
{
+ − 1321
QScriptValue ret = engine.evaluate("this.hasOwnProperty('protoProperty')");
+ − 1322
QVERIFY(ret.isBool());
+ − 1323
QVERIFY(!ret.toBool());
+ − 1324
}
+ − 1325
+ − 1326
// Custom prototype set from JS
+ − 1327
{
+ − 1328
QScriptValue ret = engine.evaluate("this.__proto__ = { 'a': 123 }; a");
+ − 1329
QVERIFY(ret.isNumber());
+ − 1330
QEXPECT_FAIL("", "QTBUG-9737", Continue);
+ − 1331
QVERIFY(ret.strictlyEquals(global.property("a")));
+ − 1332
}
+ − 1333
}
+ − 1334
0
+ − 1335
void tst_QScriptEngine::builtinFunctionNames_data()
+ − 1336
{
+ − 1337
QTest::addColumn<QString>("expression");
+ − 1338
QTest::addColumn<QString>("expectedName");
+ − 1339
+ − 1340
QTest::newRow("print") << QString("print") << QString("print");
+ − 1341
QTest::newRow("parseInt") << QString("parseInt") << QString("parseInt");
+ − 1342
QTest::newRow("parseFloat") << QString("parseFloat") << QString("parseFloat");
+ − 1343
QTest::newRow("isNaN") << QString("isNaN") << QString("isNaN");
+ − 1344
QTest::newRow("isFinite") << QString("isFinite") << QString("isFinite");
+ − 1345
QTest::newRow("decodeURI") << QString("decodeURI") << QString("decodeURI");
+ − 1346
QTest::newRow("decodeURIComponent") << QString("decodeURIComponent") << QString("decodeURIComponent");
+ − 1347
QTest::newRow("encodeURI") << QString("encodeURI") << QString("encodeURI");
+ − 1348
QTest::newRow("encodeURIComponent") << QString("encodeURIComponent") << QString("encodeURIComponent");
+ − 1349
QTest::newRow("escape") << QString("escape") << QString("escape");
+ − 1350
QTest::newRow("unescape") << QString("unescape") << QString("unescape");
+ − 1351
QTest::newRow("version") << QString("version") << QString("version");
+ − 1352
QTest::newRow("gc") << QString("gc") << QString("gc");
+ − 1353
+ − 1354
QTest::newRow("Array") << QString("Array") << QString("Array");
+ − 1355
QTest::newRow("Array.prototype.toString") << QString("Array.prototype.toString") << QString("toString");
+ − 1356
QTest::newRow("Array.prototype.toLocaleString") << QString("Array.prototype.toLocaleString") << QString("toLocaleString");
+ − 1357
QTest::newRow("Array.prototype.concat") << QString("Array.prototype.concat") << QString("concat");
+ − 1358
QTest::newRow("Array.prototype.join") << QString("Array.prototype.join") << QString("join");
+ − 1359
QTest::newRow("Array.prototype.pop") << QString("Array.prototype.pop") << QString("pop");
+ − 1360
QTest::newRow("Array.prototype.push") << QString("Array.prototype.push") << QString("push");
+ − 1361
QTest::newRow("Array.prototype.reverse") << QString("Array.prototype.reverse") << QString("reverse");
+ − 1362
QTest::newRow("Array.prototype.shift") << QString("Array.prototype.shift") << QString("shift");
+ − 1363
QTest::newRow("Array.prototype.slice") << QString("Array.prototype.slice") << QString("slice");
+ − 1364
QTest::newRow("Array.prototype.sort") << QString("Array.prototype.sort") << QString("sort");
+ − 1365
QTest::newRow("Array.prototype.splice") << QString("Array.prototype.splice") << QString("splice");
+ − 1366
QTest::newRow("Array.prototype.unshift") << QString("Array.prototype.unshift") << QString("unshift");
+ − 1367
+ − 1368
QTest::newRow("Boolean") << QString("Boolean") << QString("Boolean");
+ − 1369
QTest::newRow("Boolean.prototype.toString") << QString("Boolean.prototype.toString") << QString("toString");
+ − 1370
+ − 1371
QTest::newRow("Date") << QString("Date") << QString("Date");
+ − 1372
QTest::newRow("Date.prototype.toString") << QString("Date.prototype.toString") << QString("toString");
+ − 1373
QTest::newRow("Date.prototype.toDateString") << QString("Date.prototype.toDateString") << QString("toDateString");
+ − 1374
QTest::newRow("Date.prototype.toTimeString") << QString("Date.prototype.toTimeString") << QString("toTimeString");
+ − 1375
QTest::newRow("Date.prototype.toLocaleString") << QString("Date.prototype.toLocaleString") << QString("toLocaleString");
+ − 1376
QTest::newRow("Date.prototype.toLocaleDateString") << QString("Date.prototype.toLocaleDateString") << QString("toLocaleDateString");
+ − 1377
QTest::newRow("Date.prototype.toLocaleTimeString") << QString("Date.prototype.toLocaleTimeString") << QString("toLocaleTimeString");
+ − 1378
QTest::newRow("Date.prototype.valueOf") << QString("Date.prototype.valueOf") << QString("valueOf");
+ − 1379
QTest::newRow("Date.prototype.getTime") << QString("Date.prototype.getTime") << QString("getTime");
+ − 1380
QTest::newRow("Date.prototype.getYear") << QString("Date.prototype.getYear") << QString("getYear");
+ − 1381
QTest::newRow("Date.prototype.getFullYear") << QString("Date.prototype.getFullYear") << QString("getFullYear");
+ − 1382
QTest::newRow("Date.prototype.getUTCFullYear") << QString("Date.prototype.getUTCFullYear") << QString("getUTCFullYear");
+ − 1383
QTest::newRow("Date.prototype.getMonth") << QString("Date.prototype.getMonth") << QString("getMonth");
+ − 1384
QTest::newRow("Date.prototype.getUTCMonth") << QString("Date.prototype.getUTCMonth") << QString("getUTCMonth");
+ − 1385
QTest::newRow("Date.prototype.getDate") << QString("Date.prototype.getDate") << QString("getDate");
+ − 1386
QTest::newRow("Date.prototype.getUTCDate") << QString("Date.prototype.getUTCDate") << QString("getUTCDate");
+ − 1387
QTest::newRow("Date.prototype.getDay") << QString("Date.prototype.getDay") << QString("getDay");
+ − 1388
QTest::newRow("Date.prototype.getUTCDay") << QString("Date.prototype.getUTCDay") << QString("getUTCDay");
+ − 1389
QTest::newRow("Date.prototype.getHours") << QString("Date.prototype.getHours") << QString("getHours");
+ − 1390
QTest::newRow("Date.prototype.getUTCHours") << QString("Date.prototype.getUTCHours") << QString("getUTCHours");
+ − 1391
QTest::newRow("Date.prototype.getMinutes") << QString("Date.prototype.getMinutes") << QString("getMinutes");
+ − 1392
QTest::newRow("Date.prototype.getUTCMinutes") << QString("Date.prototype.getUTCMinutes") << QString("getUTCMinutes");
+ − 1393
QTest::newRow("Date.prototype.getSeconds") << QString("Date.prototype.getSeconds") << QString("getSeconds");
+ − 1394
QTest::newRow("Date.prototype.getUTCSeconds") << QString("Date.prototype.getUTCSeconds") << QString("getUTCSeconds");
+ − 1395
QTest::newRow("Date.prototype.getMilliseconds") << QString("Date.prototype.getMilliseconds") << QString("getMilliseconds");
+ − 1396
QTest::newRow("Date.prototype.getUTCMilliseconds") << QString("Date.prototype.getUTCMilliseconds") << QString("getUTCMilliseconds");
+ − 1397
QTest::newRow("Date.prototype.getTimezoneOffset") << QString("Date.prototype.getTimezoneOffset") << QString("getTimezoneOffset");
+ − 1398
QTest::newRow("Date.prototype.setTime") << QString("Date.prototype.setTime") << QString("setTime");
+ − 1399
QTest::newRow("Date.prototype.setMilliseconds") << QString("Date.prototype.setMilliseconds") << QString("setMilliseconds");
+ − 1400
QTest::newRow("Date.prototype.setUTCMilliseconds") << QString("Date.prototype.setUTCMilliseconds") << QString("setUTCMilliseconds");
+ − 1401
QTest::newRow("Date.prototype.setSeconds") << QString("Date.prototype.setSeconds") << QString("setSeconds");
+ − 1402
QTest::newRow("Date.prototype.setUTCSeconds") << QString("Date.prototype.setUTCSeconds") << QString("setUTCSeconds");
+ − 1403
QTest::newRow("Date.prototype.setMinutes") << QString("Date.prototype.setMinutes") << QString("setMinutes");
+ − 1404
QTest::newRow("Date.prototype.setUTCMinutes") << QString("Date.prototype.setUTCMinutes") << QString("setUTCMinutes");
+ − 1405
QTest::newRow("Date.prototype.setHours") << QString("Date.prototype.setHours") << QString("setHours");
+ − 1406
QTest::newRow("Date.prototype.setUTCHours") << QString("Date.prototype.setUTCHours") << QString("setUTCHours");
+ − 1407
QTest::newRow("Date.prototype.setDate") << QString("Date.prototype.setDate") << QString("setDate");
+ − 1408
QTest::newRow("Date.prototype.setUTCDate") << QString("Date.prototype.setUTCDate") << QString("setUTCDate");
+ − 1409
QTest::newRow("Date.prototype.setMonth") << QString("Date.prototype.setMonth") << QString("setMonth");
+ − 1410
QTest::newRow("Date.prototype.setUTCMonth") << QString("Date.prototype.setUTCMonth") << QString("setUTCMonth");
+ − 1411
QTest::newRow("Date.prototype.setYear") << QString("Date.prototype.setYear") << QString("setYear");
+ − 1412
QTest::newRow("Date.prototype.setFullYear") << QString("Date.prototype.setFullYear") << QString("setFullYear");
+ − 1413
QTest::newRow("Date.prototype.setUTCFullYear") << QString("Date.prototype.setUTCFullYear") << QString("setUTCFullYear");
+ − 1414
QTest::newRow("Date.prototype.toUTCString") << QString("Date.prototype.toUTCString") << QString("toUTCString");
+ − 1415
QTest::newRow("Date.prototype.toGMTString") << QString("Date.prototype.toGMTString") << QString("toGMTString");
+ − 1416
+ − 1417
QTest::newRow("Error") << QString("Error") << QString("Error");
+ − 1418
// QTest::newRow("Error.prototype.backtrace") << QString("Error.prototype.backtrace") << QString("backtrace");
+ − 1419
QTest::newRow("Error.prototype.toString") << QString("Error.prototype.toString") << QString("toString");
+ − 1420
+ − 1421
QTest::newRow("EvalError") << QString("EvalError") << QString("EvalError");
+ − 1422
QTest::newRow("RangeError") << QString("RangeError") << QString("RangeError");
+ − 1423
QTest::newRow("ReferenceError") << QString("ReferenceError") << QString("ReferenceError");
+ − 1424
QTest::newRow("SyntaxError") << QString("SyntaxError") << QString("SyntaxError");
+ − 1425
QTest::newRow("TypeError") << QString("TypeError") << QString("TypeError");
+ − 1426
QTest::newRow("URIError") << QString("URIError") << QString("URIError");
+ − 1427
+ − 1428
QTest::newRow("Function") << QString("Function") << QString("Function");
+ − 1429
QTest::newRow("Function.prototype.toString") << QString("Function.prototype.toString") << QString("toString");
+ − 1430
QTest::newRow("Function.prototype.apply") << QString("Function.prototype.apply") << QString("apply");
+ − 1431
QTest::newRow("Function.prototype.call") << QString("Function.prototype.call") << QString("call");
+ − 1432
QTest::newRow("Function.prototype.connect") << QString("Function.prototype.connect") << QString("connect");
+ − 1433
QTest::newRow("Function.prototype.disconnect") << QString("Function.prototype.disconnect") << QString("disconnect");
+ − 1434
+ − 1435
QTest::newRow("Math.abs") << QString("Math.abs") << QString("abs");
+ − 1436
QTest::newRow("Math.acos") << QString("Math.acos") << QString("acos");
+ − 1437
QTest::newRow("Math.asin") << QString("Math.asin") << QString("asin");
+ − 1438
QTest::newRow("Math.atan") << QString("Math.atan") << QString("atan");
+ − 1439
QTest::newRow("Math.atan2") << QString("Math.atan2") << QString("atan2");
+ − 1440
QTest::newRow("Math.ceil") << QString("Math.ceil") << QString("ceil");
+ − 1441
QTest::newRow("Math.cos") << QString("Math.cos") << QString("cos");
+ − 1442
QTest::newRow("Math.exp") << QString("Math.exp") << QString("exp");
+ − 1443
QTest::newRow("Math.floor") << QString("Math.floor") << QString("floor");
+ − 1444
QTest::newRow("Math.log") << QString("Math.log") << QString("log");
+ − 1445
QTest::newRow("Math.max") << QString("Math.max") << QString("max");
+ − 1446
QTest::newRow("Math.min") << QString("Math.min") << QString("min");
+ − 1447
QTest::newRow("Math.pow") << QString("Math.pow") << QString("pow");
+ − 1448
QTest::newRow("Math.random") << QString("Math.random") << QString("random");
+ − 1449
QTest::newRow("Math.round") << QString("Math.round") << QString("round");
+ − 1450
QTest::newRow("Math.sin") << QString("Math.sin") << QString("sin");
+ − 1451
QTest::newRow("Math.sqrt") << QString("Math.sqrt") << QString("sqrt");
+ − 1452
QTest::newRow("Math.tan") << QString("Math.tan") << QString("tan");
+ − 1453
+ − 1454
QTest::newRow("Number") << QString("Number") << QString("Number");
+ − 1455
QTest::newRow("Number.prototype.toString") << QString("Number.prototype.toString") << QString("toString");
+ − 1456
QTest::newRow("Number.prototype.toLocaleString") << QString("Number.prototype.toLocaleString") << QString("toLocaleString");
+ − 1457
QTest::newRow("Number.prototype.valueOf") << QString("Number.prototype.valueOf") << QString("valueOf");
+ − 1458
QTest::newRow("Number.prototype.toFixed") << QString("Number.prototype.toFixed") << QString("toFixed");
+ − 1459
QTest::newRow("Number.prototype.toExponential") << QString("Number.prototype.toExponential") << QString("toExponential");
+ − 1460
QTest::newRow("Number.prototype.toPrecision") << QString("Number.prototype.toPrecision") << QString("toPrecision");
+ − 1461
+ − 1462
QTest::newRow("Object") << QString("Object") << QString("Object");
+ − 1463
QTest::newRow("Object.prototype.toString") << QString("Object.prototype.toString") << QString("toString");
+ − 1464
QTest::newRow("Object.prototype.toLocaleString") << QString("Object.prototype.toLocaleString") << QString("toLocaleString");
+ − 1465
QTest::newRow("Object.prototype.valueOf") << QString("Object.prototype.valueOf") << QString("valueOf");
+ − 1466
QTest::newRow("Object.prototype.hasOwnProperty") << QString("Object.prototype.hasOwnProperty") << QString("hasOwnProperty");
+ − 1467
QTest::newRow("Object.prototype.isPrototypeOf") << QString("Object.prototype.isPrototypeOf") << QString("isPrototypeOf");
+ − 1468
QTest::newRow("Object.prototype.propertyIsEnumerable") << QString("Object.prototype.propertyIsEnumerable") << QString("propertyIsEnumerable");
+ − 1469
QTest::newRow("Object.prototype.__defineGetter__") << QString("Object.prototype.__defineGetter__") << QString("__defineGetter__");
+ − 1470
QTest::newRow("Object.prototype.__defineSetter__") << QString("Object.prototype.__defineSetter__") << QString("__defineSetter__");
+ − 1471
+ − 1472
QTest::newRow("RegExp") << QString("RegExp") << QString("RegExp");
+ − 1473
QTest::newRow("RegExp.prototype.exec") << QString("RegExp.prototype.exec") << QString("exec");
+ − 1474
QTest::newRow("RegExp.prototype.test") << QString("RegExp.prototype.test") << QString("test");
+ − 1475
QTest::newRow("RegExp.prototype.toString") << QString("RegExp.prototype.toString") << QString("toString");
+ − 1476
+ − 1477
QTest::newRow("String") << QString("String") << QString("String");
+ − 1478
QTest::newRow("String.prototype.toString") << QString("String.prototype.toString") << QString("toString");
+ − 1479
QTest::newRow("String.prototype.valueOf") << QString("String.prototype.valueOf") << QString("valueOf");
+ − 1480
QTest::newRow("String.prototype.charAt") << QString("String.prototype.charAt") << QString("charAt");
+ − 1481
QTest::newRow("String.prototype.charCodeAt") << QString("String.prototype.charCodeAt") << QString("charCodeAt");
+ − 1482
QTest::newRow("String.prototype.concat") << QString("String.prototype.concat") << QString("concat");
+ − 1483
QTest::newRow("String.prototype.indexOf") << QString("String.prototype.indexOf") << QString("indexOf");
+ − 1484
QTest::newRow("String.prototype.lastIndexOf") << QString("String.prototype.lastIndexOf") << QString("lastIndexOf");
+ − 1485
QTest::newRow("String.prototype.localeCompare") << QString("String.prototype.localeCompare") << QString("localeCompare");
+ − 1486
QTest::newRow("String.prototype.match") << QString("String.prototype.match") << QString("match");
+ − 1487
QTest::newRow("String.prototype.replace") << QString("String.prototype.replace") << QString("replace");
+ − 1488
QTest::newRow("String.prototype.search") << QString("String.prototype.search") << QString("search");
+ − 1489
QTest::newRow("String.prototype.slice") << QString("String.prototype.slice") << QString("slice");
+ − 1490
QTest::newRow("String.prototype.split") << QString("String.prototype.split") << QString("split");
+ − 1491
QTest::newRow("String.prototype.substring") << QString("String.prototype.substring") << QString("substring");
+ − 1492
QTest::newRow("String.prototype.toLowerCase") << QString("String.prototype.toLowerCase") << QString("toLowerCase");
+ − 1493
QTest::newRow("String.prototype.toLocaleLowerCase") << QString("String.prototype.toLocaleLowerCase") << QString("toLocaleLowerCase");
+ − 1494
QTest::newRow("String.prototype.toUpperCase") << QString("String.prototype.toUpperCase") << QString("toUpperCase");
+ − 1495
QTest::newRow("String.prototype.toLocaleUpperCase") << QString("String.prototype.toLocaleUpperCase") << QString("toLocaleUpperCase");
+ − 1496
}
+ − 1497
+ − 1498
void tst_QScriptEngine::builtinFunctionNames()
+ − 1499
{
+ − 1500
QFETCH(QString, expression);
+ − 1501
QFETCH(QString, expectedName);
+ − 1502
QScriptEngine eng;
+ − 1503
QScriptValue ret = eng.evaluate(QString::fromLatin1("%0.name").arg(expression));
+ − 1504
QVERIFY(ret.isString());
+ − 1505
QCOMPARE(ret.toString(), expectedName);
+ − 1506
}
+ − 1507
+ − 1508
void tst_QScriptEngine::checkSyntax_data()
+ − 1509
{
+ − 1510
QTest::addColumn<QString>("code");
+ − 1511
QTest::addColumn<int>("expectedState");
+ − 1512
QTest::addColumn<int>("errorLineNumber");
+ − 1513
QTest::addColumn<int>("errorColumnNumber");
+ − 1514
QTest::addColumn<QString>("errorMessage");
+ − 1515
+ − 1516
QTest::newRow("0")
+ − 1517
<< QString("0") << int(QScriptSyntaxCheckResult::Valid)
+ − 1518
<< -1 << -1 << "";
+ − 1519
QTest::newRow("if (")
+ − 1520
<< QString("if (\n") << int(QScriptSyntaxCheckResult::Intermediate)
+ − 1521
<< 1 << 4 << "";
+ − 1522
QTest::newRow("if else")
+ − 1523
<< QString("\nif else") << int(QScriptSyntaxCheckResult::Error)
+ − 1524
<< 2 << 4 << "Expected `('";
+ − 1525
QTest::newRow("foo[")
+ − 1526
<< QString("foo[") << int(QScriptSyntaxCheckResult::Error)
+ − 1527
<< 1 << 4 << "";
+ − 1528
QTest::newRow("foo['bar']")
+ − 1529
<< QString("foo['bar']") << int(QScriptSyntaxCheckResult::Valid)
+ − 1530
<< -1 << -1 << "";
+ − 1531
+ − 1532
QTest::newRow("/*")
+ − 1533
<< QString("/*") << int(QScriptSyntaxCheckResult::Intermediate)
+ − 1534
<< 1 << 1 << "Unclosed comment at end of file";
+ − 1535
QTest::newRow("/*\nMy comment")
+ − 1536
<< QString("/*\nMy comment") << int(QScriptSyntaxCheckResult::Intermediate)
+ − 1537
<< 1 << 1 << "Unclosed comment at end of file";
+ − 1538
QTest::newRow("/*\nMy comment */\nfoo = 10")
+ − 1539
<< QString("/*\nMy comment */\nfoo = 10") << int(QScriptSyntaxCheckResult::Valid)
+ − 1540
<< -1 << -1 << "";
+ − 1541
QTest::newRow("foo = 10 /*")
+ − 1542
<< QString("foo = 10 /*") << int(QScriptSyntaxCheckResult::Intermediate)
+ − 1543
<< -1 << -1 << "";
+ − 1544
QTest::newRow("foo = 10; /*")
+ − 1545
<< QString("foo = 10; /*") << int(QScriptSyntaxCheckResult::Intermediate)
+ − 1546
<< 1 << 11 << "Expected `end of file'";
+ − 1547
QTest::newRow("foo = 10 /* My comment */")
+ − 1548
<< QString("foo = 10 /* My comment */") << int(QScriptSyntaxCheckResult::Valid)
+ − 1549
<< -1 << -1 << "";
+ − 1550
+ − 1551
QTest::newRow("/=/")
+ − 1552
<< QString("/=/") << int(QScriptSyntaxCheckResult::Valid) << -1 << -1 << "";
+ − 1553
QTest::newRow("/=/g")
+ − 1554
<< QString("/=/g") << int(QScriptSyntaxCheckResult::Valid) << -1 << -1 << "";
+ − 1555
QTest::newRow("/a/")
+ − 1556
<< QString("/a/") << int(QScriptSyntaxCheckResult::Valid) << -1 << -1 << "";
+ − 1557
QTest::newRow("/a/g")
+ − 1558
<< QString("/a/g") << int(QScriptSyntaxCheckResult::Valid) << -1 << -1 << "";
+ − 1559
}
+ − 1560
+ − 1561
void tst_QScriptEngine::checkSyntax()
+ − 1562
{
+ − 1563
QFETCH(QString, code);
+ − 1564
QFETCH(int, expectedState);
+ − 1565
QFETCH(int, errorLineNumber);
+ − 1566
QFETCH(int, errorColumnNumber);
+ − 1567
QFETCH(QString, errorMessage);
+ − 1568
+ − 1569
QScriptSyntaxCheckResult result = QScriptEngine::checkSyntax(code);
+ − 1570
QCOMPARE(result.state(), QScriptSyntaxCheckResult::State(expectedState));
+ − 1571
QCOMPARE(result.errorLineNumber(), errorLineNumber);
+ − 1572
QCOMPARE(result.errorColumnNumber(), errorColumnNumber);
+ − 1573
QCOMPARE(result.errorMessage(), errorMessage);
+ − 1574
+ − 1575
// assignment
+ − 1576
{
+ − 1577
QScriptSyntaxCheckResult copy = result;
+ − 1578
QCOMPARE(copy.state(), result.state());
+ − 1579
QCOMPARE(copy.errorLineNumber(), result.errorLineNumber());
+ − 1580
QCOMPARE(copy.errorColumnNumber(), result.errorColumnNumber());
+ − 1581
QCOMPARE(copy.errorMessage(), result.errorMessage());
+ − 1582
}
+ − 1583
{
+ − 1584
QScriptSyntaxCheckResult copy(result);
+ − 1585
QCOMPARE(copy.state(), result.state());
+ − 1586
QCOMPARE(copy.errorLineNumber(), result.errorLineNumber());
+ − 1587
QCOMPARE(copy.errorColumnNumber(), result.errorColumnNumber());
+ − 1588
QCOMPARE(copy.errorMessage(), result.errorMessage());
+ − 1589
}
+ − 1590
}
+ − 1591
+ − 1592
void tst_QScriptEngine::canEvaluate_data()
+ − 1593
{
+ − 1594
QTest::addColumn<QString>("code");
+ − 1595
QTest::addColumn<bool>("expectSuccess");
+ − 1596
+ − 1597
QTest::newRow("") << QString("") << true;
+ − 1598
QTest::newRow("0") << QString("0") << true;
+ − 1599
QTest::newRow("!") << QString("!\n") << false;
+ − 1600
QTest::newRow("if (") << QString("if (\n") << false;
+ − 1601
QTest::newRow("if (10) //") << QString("if (10) //\n") << false;
+ − 1602
QTest::newRow("a = 1; if (") << QString("a = 1;\nif (\n") << false;
+ − 1603
QTest::newRow("./test.js") << QString("./test.js\n") << true;
+ − 1604
QTest::newRow("if (0) print(1)") << QString("if (0)\nprint(1)\n") << true;
+ − 1605
QTest::newRow("0 = ") << QString("0 = \n") << false;
+ − 1606
QTest::newRow("0 = 0") << QString("0 = 0\n") << true;
+ − 1607
QTest::newRow("foo[") << QString("foo[") << true; // automatic semicolon will be inserted
+ − 1608
QTest::newRow("foo[") << QString("foo[\n") << false;
+ − 1609
QTest::newRow("foo['bar']") << QString("foo['bar']") << true;
+ − 1610
+ − 1611
QTest::newRow("/*") << QString("/*") << false;
+ − 1612
QTest::newRow("/*\nMy comment") << QString("/*\nMy comment") << false;
+ − 1613
QTest::newRow("/*\nMy comment */\nfoo = 10") << QString("/*\nMy comment */\nfoo = 10") << true;
+ − 1614
QTest::newRow("foo = 10 /*") << QString("foo = 10 /*") << false;
+ − 1615
QTest::newRow("foo = 10; /*") << QString("foo = 10; /*") << false;
+ − 1616
QTest::newRow("foo = 10 /* My comment */") << QString("foo = 10 /* My comment */") << true;
+ − 1617
+ − 1618
QTest::newRow("/=/") << QString("/=/") << true;
+ − 1619
QTest::newRow("/=/g") << QString("/=/g") << true;
+ − 1620
QTest::newRow("/a/") << QString("/a/") << true;
+ − 1621
QTest::newRow("/a/g") << QString("/a/g") << true;
+ − 1622
}
+ − 1623
+ − 1624
void tst_QScriptEngine::canEvaluate()
+ − 1625
{
+ − 1626
QFETCH(QString, code);
+ − 1627
QFETCH(bool, expectSuccess);
+ − 1628
+ − 1629
QScriptEngine eng;
+ − 1630
QCOMPARE(eng.canEvaluate(code), expectSuccess);
+ − 1631
}
+ − 1632
+ − 1633
void tst_QScriptEngine::evaluate_data()
+ − 1634
{
+ − 1635
QTest::addColumn<QString>("code");
+ − 1636
QTest::addColumn<int>("lineNumber");
+ − 1637
QTest::addColumn<bool>("expectHadError");
+ − 1638
QTest::addColumn<int>("expectErrorLineNumber");
+ − 1639
+ − 1640
QTest::newRow("(newline)") << QString("\n") << -1 << false << -1;
+ − 1641
QTest::newRow("0 //") << QString("0 //") << -1 << false << -1;
+ − 1642
QTest::newRow("/* */") << QString("/* */") << -1 << false << -1;
+ − 1643
QTest::newRow("//") << QString("//") << -1 << false << -1;
+ − 1644
QTest::newRow("(spaces)") << QString(" ") << -1 << false << -1;
+ − 1645
QTest::newRow("(empty)") << QString("") << -1 << false << -1;
+ − 1646
QTest::newRow("0") << QString("0") << -1 << false << -1;
+ − 1647
QTest::newRow("0=1") << QString("\n0=1;\n") << -1 << true << 2;
+ − 1648
QTest::newRow("a=1") << QString("a=1\n") << -1 << false << -1;
+ − 1649
QTest::newRow("a=1;K") << QString("a=1;\nK") << -1 << true << 2;
+ − 1650
+ − 1651
QTest::newRow("f()") << QString("function f()\n"
+ − 1652
"{\n"
+ − 1653
" var a;\n"
+ − 1654
" var b=\";\n" // here's the error
+ − 1655
"}\n"
+ − 1656
"f();\n")
+ − 1657
<< -1 << true << 4;
+ − 1658
+ − 1659
QTest::newRow("0") << QString("0") << 10 << false << -1;
+ − 1660
QTest::newRow("0=1") << QString("\n\n0=1\n") << 10 << true << 13;
+ − 1661
QTest::newRow("a=1") << QString("a=1\n") << 10 << false << -1;
+ − 1662
QTest::newRow("a=1;K") << QString("a=1;\n\nK") << 10 << true << 12;
+ − 1663
+ − 1664
QTest::newRow("f()") << QString("function f()\n"
+ − 1665
"{\n"
+ − 1666
" var a;\n"
+ − 1667
"\n\n"
+ − 1668
" var b=\";\n" // here's the error
+ − 1669
"}\n"
+ − 1670
"f();\n")
+ − 1671
<< 10 << true << 15;
+ − 1672
QTest::newRow("functionThatDoesntExist()")
+ − 1673
<< QString(";\n;\n;\nfunctionThatDoesntExist()")
+ − 1674
<< -1 << true << 4;
+ − 1675
QTest::newRow("for (var p in this) { continue labelThatDoesntExist; }")
+ − 1676
<< QString("for (var p in this) {\ncontinue labelThatDoesntExist; }")
+ − 1677
<< 4 << true << 5;
+ − 1678
QTest::newRow("duplicateLabel: { duplicateLabel: ; }")
+ − 1679
<< QString("duplicateLabel: { duplicateLabel: ; }")
+ − 1680
<< 12 << true << 12;
+ − 1681
+ − 1682
QTest::newRow("/=/") << QString("/=/") << -1 << false << -1;
+ − 1683
QTest::newRow("/=/g") << QString("/=/g") << -1 << false << -1;
+ − 1684
QTest::newRow("/a/") << QString("/a/") << -1 << false << -1;
+ − 1685
QTest::newRow("/a/g") << QString("/a/g") << -1 << false << -1;
+ − 1686
QTest::newRow("/a/gim") << QString("/a/gim") << -1 << false << -1;
+ − 1687
QTest::newRow("/a/gimp") << QString("/a/gimp") << 1 << true << 1;
+ − 1688
}
+ − 1689
+ − 1690
void tst_QScriptEngine::evaluate()
+ − 1691
{
+ − 1692
QFETCH(QString, code);
+ − 1693
QFETCH(int, lineNumber);
+ − 1694
QFETCH(bool, expectHadError);
+ − 1695
QFETCH(int, expectErrorLineNumber);
+ − 1696
+ − 1697
QScriptEngine eng;
+ − 1698
QScriptValue ret;
+ − 1699
if (lineNumber != -1)
+ − 1700
ret = eng.evaluate(code, /*fileName =*/QString(), lineNumber);
+ − 1701
else
+ − 1702
ret = eng.evaluate(code);
+ − 1703
QCOMPARE(eng.hasUncaughtException(), expectHadError);
+ − 1704
QCOMPARE(eng.uncaughtExceptionLineNumber(), expectErrorLineNumber);
+ − 1705
if (eng.hasUncaughtException() && ret.isError())
+ − 1706
QVERIFY(ret.property("lineNumber").strictlyEquals(QScriptValue(&eng, expectErrorLineNumber)));
+ − 1707
else
+ − 1708
QVERIFY(eng.uncaughtExceptionBacktrace().isEmpty());
+ − 1709
}
+ − 1710
+ − 1711
static QScriptValue eval_nested(QScriptContext *ctx, QScriptEngine *eng)
+ − 1712
{
+ − 1713
QScriptValue result = eng->newObject();
+ − 1714
eng->evaluate("var bar = 'local';");
+ − 1715
result.setProperty("thisObjectIdBefore", ctx->thisObject().property("id"));
+ − 1716
QScriptValue evaluatedThisObject = eng->evaluate("this");
+ − 1717
result.setProperty("thisObjectIdAfter", ctx->thisObject().property("id"));
+ − 1718
result.setProperty("evaluatedThisObjectId", evaluatedThisObject.property("id"));
+ − 1719
result.setProperty("local_bar", eng->evaluate("bar"));
+ − 1720
+ − 1721
return result;
+ − 1722
}
+ − 1723
+ − 1724
void tst_QScriptEngine::nestedEvaluate()
+ − 1725
{
+ − 1726
QScriptEngine eng;
+ − 1727
QScriptValue fun = eng.newFunction(eval_nested);
+ − 1728
eng.globalObject().setProperty("fun", fun);
+ − 1729
{
+ − 1730
QScriptValue result = eng.evaluate("o = { id:'foo'}; o.fun = fun; o.fun()");
+ − 1731
QCOMPARE(result.property("local_bar").toString(), QString("local"));
+ − 1732
QCOMPARE(result.property("thisObjectIdBefore").toString(), QString("foo"));
+ − 1733
QCOMPARE(result.property("thisObjectIdAfter").toString(), QString("foo"));
+ − 1734
QCOMPARE(result.property("evaluatedThisObjectId").toString(), QString("foo"));
+ − 1735
QScriptValue bar = eng.evaluate("bar");
+ − 1736
QVERIFY(bar.isError());
+ − 1737
QCOMPARE(bar.toString(), QString::fromLatin1("ReferenceError: Can't find variable: bar"));
+ − 1738
}
+ − 1739
+ − 1740
{
+ − 1741
QScriptValue result = fun.call(eng.evaluate("p = { id:'foo' }") , QScriptValueList() );
+ − 1742
QCOMPARE(result.property("local_bar").toString(), QString("local"));
+ − 1743
QCOMPARE(result.property("thisObjectIdBefore").toString(), QString("foo"));
+ − 1744
QCOMPARE(result.property("thisObjectIdAfter").toString(), QString("foo"));
+ − 1745
QCOMPARE(result.property("evaluatedThisObjectId").toString(), QString("foo"));
+ − 1746
QScriptValue bar = eng.evaluate("bar");
+ − 1747
QVERIFY(bar.isError());
+ − 1748
QCOMPARE(bar.toString(), QString::fromLatin1("ReferenceError: Can't find variable: bar"));
+ − 1749
}
+ − 1750
}
+ − 1751
+ − 1752
void tst_QScriptEngine::uncaughtException()
+ − 1753
{
+ − 1754
QScriptEngine eng;
+ − 1755
QScriptValue fun = eng.newFunction(myFunction);
+ − 1756
QScriptValue throwFun = eng.newFunction(myThrowingFunction);
+ − 1757
for (int x = -1; x < 2; ++x) {
+ − 1758
{
+ − 1759
QScriptValue ret = eng.evaluate("a = 10;\nb = 20;\n0 = 0;\n", /*fileName=*/QString(), /*lineNumber=*/x);
+ − 1760
QVERIFY(eng.hasUncaughtException());
+ − 1761
QCOMPARE(eng.uncaughtExceptionLineNumber(), x+2);
+ − 1762
QVERIFY(eng.uncaughtException().strictlyEquals(ret));
+ − 1763
(void)ret.toString();
+ − 1764
QVERIFY(eng.hasUncaughtException());
+ − 1765
QVERIFY(eng.uncaughtException().strictlyEquals(ret));
+ − 1766
QVERIFY(fun.call().isNull());
+ − 1767
QVERIFY(eng.hasUncaughtException());
+ − 1768
QCOMPARE(eng.uncaughtExceptionLineNumber(), x+2);
+ − 1769
QVERIFY(eng.uncaughtException().strictlyEquals(ret));
+ − 1770
eng.clearExceptions();
+ − 1771
QVERIFY(!eng.hasUncaughtException());
+ − 1772
QCOMPARE(eng.uncaughtExceptionLineNumber(), -1);
+ − 1773
QVERIFY(!eng.uncaughtException().isValid());
+ − 1774
+ − 1775
eng.evaluate("2 = 3");
+ − 1776
QVERIFY(eng.hasUncaughtException());
+ − 1777
QScriptValue ret2 = throwFun.call();
+ − 1778
QVERIFY(ret2.isError());
+ − 1779
QVERIFY(eng.hasUncaughtException());
+ − 1780
QVERIFY(eng.uncaughtException().strictlyEquals(ret2));
+ − 1781
QCOMPARE(eng.uncaughtExceptionLineNumber(), 0);
+ − 1782
eng.clearExceptions();
+ − 1783
QVERIFY(!eng.hasUncaughtException());
+ − 1784
eng.evaluate("1 + 2");
+ − 1785
QVERIFY(!eng.hasUncaughtException());
+ − 1786
}
+ − 1787
{
+ − 1788
QScriptValue ret = eng.evaluate("a = 10");
+ − 1789
QVERIFY(!eng.hasUncaughtException());
+ − 1790
QVERIFY(!eng.uncaughtException().isValid());
+ − 1791
}
+ − 1792
{
+ − 1793
QScriptValue ret = eng.evaluate("1 = 2");
+ − 1794
QVERIFY(eng.hasUncaughtException());
+ − 1795
eng.clearExceptions();
+ − 1796
QVERIFY(!eng.hasUncaughtException());
+ − 1797
}
+ − 1798
{
+ − 1799
eng.globalObject().setProperty("throwFun", throwFun);
+ − 1800
eng.evaluate("1;\nthrowFun();");
+ − 1801
QVERIFY(eng.hasUncaughtException());
+ − 1802
QCOMPARE(eng.uncaughtExceptionLineNumber(), 2);
+ − 1803
eng.clearExceptions();
+ − 1804
QVERIFY(!eng.hasUncaughtException());
+ − 1805
}
+ − 1806
}
+ − 1807
}
+ − 1808
+ − 1809
void tst_QScriptEngine::errorMessage_QT679()
+ − 1810
{
+ − 1811
QScriptEngine engine;
+ − 1812
engine.globalObject().setProperty("foo", 15);
+ − 1813
QScriptValue error = engine.evaluate("'hello world';\nfoo.bar.blah");
+ − 1814
QVERIFY(error.isError());
+ − 1815
QCOMPARE(error.toString(), QString::fromLatin1("TypeError: Result of expression 'foo.bar' [undefined] is not an object."));
+ − 1816
}
+ − 1817
+ − 1818
struct Foo {
+ − 1819
public:
+ − 1820
int x, y;
+ − 1821
Foo() : x(-1), y(-1) { }
+ − 1822
};
+ − 1823
+ − 1824
Q_DECLARE_METATYPE(Foo)
+ − 1825
Q_DECLARE_METATYPE(Foo*)
+ − 1826
+ − 1827
void tst_QScriptEngine::getSetDefaultPrototype()
+ − 1828
{
+ − 1829
QScriptEngine eng;
+ − 1830
{
+ − 1831
QScriptValue object = eng.newObject();
+ − 1832
QCOMPARE(eng.defaultPrototype(qMetaTypeId<int>()).isValid(), false);
+ − 1833
eng.setDefaultPrototype(qMetaTypeId<int>(), object);
+ − 1834
QCOMPARE(eng.defaultPrototype(qMetaTypeId<int>()).strictlyEquals(object), true);
+ − 1835
QScriptValue value = eng.newVariant(int(123));
+ − 1836
QCOMPARE(value.prototype().isObject(), true);
+ − 1837
QCOMPARE(value.prototype().strictlyEquals(object), true);
+ − 1838
+ − 1839
eng.setDefaultPrototype(qMetaTypeId<int>(), QScriptValue());
+ − 1840
QCOMPARE(eng.defaultPrototype(qMetaTypeId<int>()).isValid(), false);
+ − 1841
QScriptValue value2 = eng.newVariant(int(123));
+ − 1842
QCOMPARE(value2.prototype().strictlyEquals(object), false);
+ − 1843
}
+ − 1844
{
+ − 1845
QScriptValue object = eng.newObject();
+ − 1846
QCOMPARE(eng.defaultPrototype(qMetaTypeId<Foo>()).isValid(), false);
+ − 1847
eng.setDefaultPrototype(qMetaTypeId<Foo>(), object);
+ − 1848
QCOMPARE(eng.defaultPrototype(qMetaTypeId<Foo>()).strictlyEquals(object), true);
+ − 1849
QScriptValue value = eng.newVariant(qVariantFromValue(Foo()));
+ − 1850
QCOMPARE(value.prototype().isObject(), true);
+ − 1851
QCOMPARE(value.prototype().strictlyEquals(object), true);
+ − 1852
+ − 1853
eng.setDefaultPrototype(qMetaTypeId<Foo>(), QScriptValue());
+ − 1854
QCOMPARE(eng.defaultPrototype(qMetaTypeId<Foo>()).isValid(), false);
+ − 1855
QScriptValue value2 = eng.newVariant(qVariantFromValue(Foo()));
+ − 1856
QCOMPARE(value2.prototype().strictlyEquals(object), false);
+ − 1857
}
+ − 1858
}
+ − 1859
+ − 1860
static QScriptValue fooToScriptValue(QScriptEngine *eng, const Foo &foo)
+ − 1861
{
+ − 1862
QScriptValue obj = eng->newObject();
+ − 1863
obj.setProperty("x", QScriptValue(eng, foo.x));
+ − 1864
obj.setProperty("y", QScriptValue(eng, foo.y));
+ − 1865
return obj;
+ − 1866
}
+ − 1867
+ − 1868
static void fooFromScriptValue(const QScriptValue &value, Foo &foo)
+ − 1869
{
+ − 1870
foo.x = value.property("x").toInt32();
+ − 1871
foo.y = value.property("y").toInt32();
+ − 1872
}
+ − 1873
+ − 1874
static QScriptValue fooToScriptValueV2(QScriptEngine *eng, const Foo &foo)
+ − 1875
{
+ − 1876
return QScriptValue(eng, foo.x);
+ − 1877
}
+ − 1878
+ − 1879
static void fooFromScriptValueV2(const QScriptValue &value, Foo &foo)
+ − 1880
{
+ − 1881
foo.x = value.toInt32();
+ − 1882
}
+ − 1883
+ − 1884
Q_DECLARE_METATYPE(QLinkedList<QString>)
+ − 1885
Q_DECLARE_METATYPE(QList<Foo>)
+ − 1886
Q_DECLARE_METATYPE(QVector<QChar>)
+ − 1887
Q_DECLARE_METATYPE(QStack<int>)
+ − 1888
Q_DECLARE_METATYPE(QQueue<char>)
+ − 1889
Q_DECLARE_METATYPE(QLinkedList<QStack<int> >)
+ − 1890
+ − 1891
void tst_QScriptEngine::valueConversion()
+ − 1892
{
+ − 1893
QScriptEngine eng;
+ − 1894
{
+ − 1895
QScriptValue num = qScriptValueFromValue(&eng, 123);
+ − 1896
QCOMPARE(num.isNumber(), true);
+ − 1897
QCOMPARE(num.strictlyEquals(QScriptValue(&eng, 123)), true);
+ − 1898
+ − 1899
int inum = qScriptValueToValue<int>(num);
+ − 1900
QCOMPARE(inum, 123);
+ − 1901
+ − 1902
QString snum = qScriptValueToValue<QString>(num);
+ − 1903
QCOMPARE(snum, QLatin1String("123"));
+ − 1904
}
+ − 1905
#ifndef QT_NO_MEMBER_TEMPLATES
+ − 1906
{
+ − 1907
QScriptValue num = eng.toScriptValue(123);
+ − 1908
QCOMPARE(num.isNumber(), true);
+ − 1909
QCOMPARE(num.strictlyEquals(QScriptValue(&eng, 123)), true);
+ − 1910
+ − 1911
int inum = eng.fromScriptValue<int>(num);
+ − 1912
QCOMPARE(inum, 123);
+ − 1913
+ − 1914
QString snum = eng.fromScriptValue<QString>(num);
+ − 1915
QCOMPARE(snum, QLatin1String("123"));
+ − 1916
}
+ − 1917
#endif
+ − 1918
{
+ − 1919
QScriptValue num(&eng, 123);
+ − 1920
QCOMPARE(qScriptValueToValue<char>(num), char(123));
+ − 1921
QCOMPARE(qScriptValueToValue<unsigned char>(num), (unsigned char)(123));
+ − 1922
QCOMPARE(qScriptValueToValue<short>(num), short(123));
+ − 1923
QCOMPARE(qScriptValueToValue<unsigned short>(num), (unsigned short)(123));
+ − 1924
QCOMPARE(qScriptValueToValue<float>(num), float(123));
+ − 1925
QCOMPARE(qScriptValueToValue<double>(num), double(123));
+ − 1926
QCOMPARE(qScriptValueToValue<qlonglong>(num), qlonglong(123));
+ − 1927
QCOMPARE(qScriptValueToValue<qulonglong>(num), qulonglong(123));
+ − 1928
}
+ − 1929
{
+ − 1930
QScriptValue num(123);
+ − 1931
QCOMPARE(qScriptValueToValue<char>(num), char(123));
+ − 1932
QCOMPARE(qScriptValueToValue<unsigned char>(num), (unsigned char)(123));
+ − 1933
QCOMPARE(qScriptValueToValue<short>(num), short(123));
+ − 1934
QCOMPARE(qScriptValueToValue<unsigned short>(num), (unsigned short)(123));
+ − 1935
QCOMPARE(qScriptValueToValue<float>(num), float(123));
+ − 1936
QCOMPARE(qScriptValueToValue<double>(num), double(123));
+ − 1937
QCOMPARE(qScriptValueToValue<qlonglong>(num), qlonglong(123));
+ − 1938
QCOMPARE(qScriptValueToValue<qulonglong>(num), qulonglong(123));
+ − 1939
}
+ − 1940
+ − 1941
{
+ − 1942
QScriptValue num = qScriptValueFromValue(&eng, Q_INT64_C(0x100000000));
+ − 1943
QCOMPARE(qScriptValueToValue<qlonglong>(num), Q_INT64_C(0x100000000));
+ − 1944
QCOMPARE(qScriptValueToValue<qulonglong>(num), Q_UINT64_C(0x100000000));
+ − 1945
}
+ − 1946
+ − 1947
{
+ − 1948
QChar c = QLatin1Char('c');
+ − 1949
QScriptValue str = QScriptValue(&eng, "ciao");
+ − 1950
QCOMPARE(qScriptValueToValue<QChar>(str), c);
+ − 1951
QScriptValue code = QScriptValue(&eng, c.unicode());
+ − 1952
QCOMPARE(qScriptValueToValue<QChar>(code), c);
+ − 1953
QCOMPARE(qScriptValueToValue<QChar>(qScriptValueFromValue(&eng, c)), c);
+ − 1954
}
+ − 1955
+ − 1956
{
+ − 1957
// a type that we don't have built-in conversion of
+ − 1958
// (it's stored as a variant)
+ − 1959
QTime tm(1, 2, 3, 4);
+ − 1960
QScriptValue val = qScriptValueFromValue(&eng, tm);
+ − 1961
QCOMPARE(qScriptValueToValue<QTime>(val), tm);
+ − 1962
}
+ − 1963
+ − 1964
{
+ − 1965
Foo foo;
+ − 1966
foo.x = 12;
+ − 1967
foo.y = 34;
+ − 1968
QScriptValue fooVal = qScriptValueFromValue(&eng, foo);
+ − 1969
QCOMPARE(fooVal.isVariant(), true);
+ − 1970
+ − 1971
Foo foo2 = qScriptValueToValue<Foo>(fooVal);
+ − 1972
QCOMPARE(foo2.x, foo.x);
+ − 1973
QCOMPARE(foo2.y, foo.y);
+ − 1974
}
+ − 1975
+ − 1976
qScriptRegisterMetaType<Foo>(&eng, fooToScriptValue, fooFromScriptValue);
+ − 1977
+ − 1978
{
+ − 1979
Foo foo;
+ − 1980
foo.x = 12;
+ − 1981
foo.y = 34;
+ − 1982
QScriptValue fooVal = qScriptValueFromValue(&eng, foo);
+ − 1983
QCOMPARE(fooVal.isObject(), true);
+ − 1984
QVERIFY(fooVal.prototype().strictlyEquals(eng.evaluate("Object.prototype")));
+ − 1985
QCOMPARE(fooVal.property("x").strictlyEquals(QScriptValue(&eng, 12)), true);
+ − 1986
QCOMPARE(fooVal.property("y").strictlyEquals(QScriptValue(&eng, 34)), true);
+ − 1987
fooVal.setProperty("x", QScriptValue(&eng, 56));
+ − 1988
fooVal.setProperty("y", QScriptValue(&eng, 78));
+ − 1989
+ − 1990
Foo foo2 = qScriptValueToValue<Foo>(fooVal);
+ − 1991
QCOMPARE(foo2.x, 56);
+ − 1992
QCOMPARE(foo2.y, 78);
+ − 1993
+ − 1994
QScriptValue fooProto = eng.newObject();
+ − 1995
eng.setDefaultPrototype(qMetaTypeId<Foo>(), fooProto);
+ − 1996
QScriptValue fooVal2 = qScriptValueFromValue(&eng, foo2);
+ − 1997
QVERIFY(fooVal2.prototype().strictlyEquals(fooProto));
+ − 1998
QVERIFY(fooVal2.property("x").strictlyEquals(QScriptValue(&eng, 56)));
+ − 1999
QVERIFY(fooVal2.property("y").strictlyEquals(QScriptValue(&eng, 78)));
+ − 2000
}
+ − 2001
+ − 2002
qScriptRegisterSequenceMetaType<QLinkedList<QString> >(&eng);
+ − 2003
+ − 2004
{
+ − 2005
QLinkedList<QString> lst;
+ − 2006
lst << QLatin1String("foo") << QLatin1String("bar");
+ − 2007
QScriptValue lstVal = qScriptValueFromValue(&eng, lst);
+ − 2008
QCOMPARE(lstVal.isArray(), true);
+ − 2009
QCOMPARE(lstVal.property("length").toInt32(), 2);
+ − 2010
QCOMPARE(lstVal.property("0").isString(), true);
+ − 2011
QCOMPARE(lstVal.property("0").toString(), QLatin1String("foo"));
+ − 2012
QCOMPARE(lstVal.property("1").isString(), true);
+ − 2013
QCOMPARE(lstVal.property("1").toString(), QLatin1String("bar"));
+ − 2014
}
+ − 2015
+ − 2016
qScriptRegisterSequenceMetaType<QList<Foo> >(&eng);
+ − 2017
qScriptRegisterSequenceMetaType<QStack<int> >(&eng);
+ − 2018
qScriptRegisterSequenceMetaType<QVector<QChar> >(&eng);
+ − 2019
qScriptRegisterSequenceMetaType<QQueue<char> >(&eng);
+ − 2020
qScriptRegisterSequenceMetaType<QLinkedList<QStack<int> > >(&eng);
+ − 2021
+ − 2022
{
+ − 2023
QLinkedList<QStack<int> > lst;
+ − 2024
QStack<int> first; first << 13 << 49; lst << first;
+ − 2025
QStack<int> second; second << 99999;lst << second;
+ − 2026
QScriptValue lstVal = qScriptValueFromValue(&eng, lst);
+ − 2027
QCOMPARE(lstVal.isArray(), true);
+ − 2028
QCOMPARE(lstVal.property("length").toInt32(), 2);
+ − 2029
QCOMPARE(lstVal.property("0").isArray(), true);
+ − 2030
QCOMPARE(lstVal.property("0").property("length").toInt32(), 2);
+ − 2031
QCOMPARE(lstVal.property("0").property("0").toInt32(), first.at(0));
+ − 2032
QCOMPARE(lstVal.property("0").property("1").toInt32(), first.at(1));
+ − 2033
QCOMPARE(lstVal.property("1").isArray(), true);
+ − 2034
QCOMPARE(lstVal.property("1").property("length").toInt32(), 1);
+ − 2035
QCOMPARE(lstVal.property("1").property("0").toInt32(), second.at(0));
+ − 2036
QCOMPARE(qscriptvalue_cast<QStack<int> >(lstVal.property("0")), first);
+ − 2037
QCOMPARE(qscriptvalue_cast<QStack<int> >(lstVal.property("1")), second);
+ − 2038
QCOMPARE(qscriptvalue_cast<QLinkedList<QStack<int> > >(lstVal), lst);
+ − 2039
}
+ − 2040
+ − 2041
// pointers
+ − 2042
{
+ − 2043
Foo foo;
+ − 2044
{
+ − 2045
QScriptValue v = qScriptValueFromValue(&eng, &foo);
+ − 2046
Foo *pfoo = qscriptvalue_cast<Foo*>(v);
+ − 2047
QCOMPARE(pfoo, &foo);
+ − 2048
}
+ − 2049
{
+ − 2050
Foo *pfoo = 0;
+ − 2051
QScriptValue v = qScriptValueFromValue(&eng, pfoo);
+ − 2052
QCOMPARE(v.isNull(), true);
+ − 2053
QVERIFY(qscriptvalue_cast<Foo*>(v) == 0);
+ − 2054
}
+ − 2055
}
+ − 2056
+ − 2057
// QList<int> and QObjectList should be converted from/to arrays by default
+ − 2058
{
+ − 2059
QList<int> lst;
+ − 2060
lst << 1 << 2 << 3;
+ − 2061
QScriptValue val = qScriptValueFromValue(&eng, lst);
+ − 2062
QVERIFY(val.isArray());
+ − 2063
QCOMPARE(val.property("length").toInt32(), lst.size());
+ − 2064
QCOMPARE(val.property(0).toInt32(), lst.at(0));
+ − 2065
QCOMPARE(val.property(1).toInt32(), lst.at(1));
+ − 2066
QCOMPARE(val.property(2).toInt32(), lst.at(2));
+ − 2067
+ − 2068
QCOMPARE(qscriptvalue_cast<QList<int> >(val), lst);
+ − 2069
}
+ − 2070
{
+ − 2071
QObjectList lst;
+ − 2072
lst << this;
+ − 2073
QScriptValue val = qScriptValueFromValue(&eng, lst);
+ − 2074
QVERIFY(val.isArray());
+ − 2075
QCOMPARE(val.property("length").toInt32(), lst.size());
+ − 2076
QCOMPARE(val.property(0).toQObject(), (QObject *)this);
+ − 2077
+ − 2078
QCOMPARE(qscriptvalue_cast<QObjectList>(val), lst);
+ − 2079
}
+ − 2080
+ − 2081
// qScriptValueFromValue() should be "smart" when the argument is a QVariant
+ − 2082
{
+ − 2083
QScriptValue val = qScriptValueFromValue(&eng, QVariant());
+ − 2084
QVERIFY(!val.isVariant());
+ − 2085
QVERIFY(val.isUndefined());
+ − 2086
}
+ − 2087
{
+ − 2088
QScriptValue val = qScriptValueFromValue(&eng, QVariant(true));
+ − 2089
QVERIFY(!val.isVariant());
+ − 2090
QVERIFY(val.isBoolean());
+ − 2091
QCOMPARE(val.toBoolean(), true);
+ − 2092
}
+ − 2093
{
+ − 2094
QScriptValue val = qScriptValueFromValue(&eng, QVariant(int(123)));
+ − 2095
QVERIFY(!val.isVariant());
+ − 2096
QVERIFY(val.isNumber());
+ − 2097
QCOMPARE(val.toNumber(), qsreal(123));
+ − 2098
}
+ − 2099
{
+ − 2100
QScriptValue val = qScriptValueFromValue(&eng, QVariant(qsreal(1.25)));
+ − 2101
QVERIFY(!val.isVariant());
+ − 2102
QVERIFY(val.isNumber());
+ − 2103
QCOMPARE(val.toNumber(), qsreal(1.25));
+ − 2104
}
+ − 2105
{
+ − 2106
QString str = QString::fromLatin1("ciao");
+ − 2107
QScriptValue val = qScriptValueFromValue(&eng, QVariant(str));
+ − 2108
QVERIFY(!val.isVariant());
+ − 2109
QVERIFY(val.isString());
+ − 2110
QCOMPARE(val.toString(), str);
+ − 2111
}
+ − 2112
{
+ − 2113
QScriptValue val = qScriptValueFromValue(&eng, qVariantFromValue((QObject*)this));
+ − 2114
QVERIFY(!val.isVariant());
+ − 2115
QVERIFY(val.isQObject());
+ − 2116
QCOMPARE(val.toQObject(), (QObject*)this);
+ − 2117
}
+ − 2118
{
+ − 2119
QVariant var = qVariantFromValue(QPoint(123, 456));
+ − 2120
QScriptValue val = qScriptValueFromValue(&eng, var);
+ − 2121
QVERIFY(val.isVariant());
+ − 2122
QCOMPARE(val.toVariant(), var);
+ − 2123
}
+ − 2124
+ − 2125
// task 248802
+ − 2126
qScriptRegisterMetaType<Foo>(&eng, fooToScriptValueV2, fooFromScriptValueV2);
+ − 2127
{
+ − 2128
QScriptValue num(&eng, 123);
+ − 2129
Foo foo = qScriptValueToValue<Foo>(num);
+ − 2130
QCOMPARE(foo.x, 123);
+ − 2131
}
+ − 2132
{
+ − 2133
QScriptValue num(123);
+ − 2134
Foo foo = qScriptValueToValue<Foo>(num);
+ − 2135
QCOMPARE(foo.x, -1);
+ − 2136
}
+ − 2137
{
+ − 2138
QScriptValue str(&eng, "123");
+ − 2139
Foo foo = qScriptValueToValue<Foo>(str);
+ − 2140
QCOMPARE(foo.x, 123);
+ − 2141
}
+ − 2142
+ − 2143
// more built-in types
+ − 2144
{
+ − 2145
QScriptValue val = qScriptValueFromValue(&eng, uint(123));
+ − 2146
QVERIFY(val.isNumber());
+ − 2147
QCOMPARE(val.toInt32(), 123);
+ − 2148
}
+ − 2149
{
+ − 2150
QScriptValue val = qScriptValueFromValue(&eng, qulonglong(123));
+ − 2151
QVERIFY(val.isNumber());
+ − 2152
QCOMPARE(val.toInt32(), 123);
+ − 2153
}
+ − 2154
{
+ − 2155
QScriptValue val = qScriptValueFromValue(&eng, float(123));
+ − 2156
QVERIFY(val.isNumber());
+ − 2157
QCOMPARE(val.toInt32(), 123);
+ − 2158
}
+ − 2159
{
+ − 2160
QScriptValue val = qScriptValueFromValue(&eng, short(123));
+ − 2161
QVERIFY(val.isNumber());
+ − 2162
QCOMPARE(val.toInt32(), 123);
+ − 2163
}
+ − 2164
{
+ − 2165
QScriptValue val = qScriptValueFromValue(&eng, ushort(123));
+ − 2166
QVERIFY(val.isNumber());
+ − 2167
QCOMPARE(val.toInt32(), 123);
+ − 2168
}
+ − 2169
{
+ − 2170
QScriptValue val = qScriptValueFromValue(&eng, char(123));
+ − 2171
QVERIFY(val.isNumber());
+ − 2172
QCOMPARE(val.toInt32(), 123);
+ − 2173
}
+ − 2174
{
+ − 2175
QScriptValue val = qScriptValueFromValue(&eng, uchar(123));
+ − 2176
QVERIFY(val.isNumber());
+ − 2177
QCOMPARE(val.toInt32(), 123);
+ − 2178
}
+ − 2179
{
+ − 2180
QDateTime in = QDateTime::currentDateTime();
+ − 2181
QScriptValue val = qScriptValueFromValue(&eng, in);
+ − 2182
QVERIFY(val.isDate());
+ − 2183
QCOMPARE(val.toDateTime(), in);
+ − 2184
}
+ − 2185
{
+ − 2186
QDate in = QDate::currentDate();
+ − 2187
QScriptValue val = qScriptValueFromValue(&eng, in);
+ − 2188
QVERIFY(val.isDate());
+ − 2189
QCOMPARE(val.toDateTime().date(), in);
+ − 2190
}
+ − 2191
{
+ − 2192
QRegExp in = QRegExp("foo");
+ − 2193
QScriptValue val = qScriptValueFromValue(&eng, in);
+ − 2194
QVERIFY(val.isRegExp());
+ − 2195
QRegExp out = val.toRegExp();
3
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 2196
QEXPECT_FAIL("", "QTBUG-6136: JSC-based back-end doesn't preserve QRegExp::patternSyntax (always uses RegExp2)", Continue);
0
+ − 2197
QCOMPARE(out.patternSyntax(), in.patternSyntax());
+ − 2198
QCOMPARE(out.pattern(), in.pattern());
+ − 2199
QCOMPARE(out.caseSensitivity(), in.caseSensitivity());
+ − 2200
QCOMPARE(out.isMinimal(), in.isMinimal());
+ − 2201
}
+ − 2202
{
+ − 2203
QRegExp in = QRegExp("foo", Qt::CaseSensitive, QRegExp::RegExp2);
+ − 2204
QScriptValue val = qScriptValueFromValue(&eng, in);
+ − 2205
QVERIFY(val.isRegExp());
+ − 2206
QCOMPARE(val.toRegExp(), in);
+ − 2207
}
+ − 2208
{
+ − 2209
QRegExp in = QRegExp("foo");
+ − 2210
in.setMinimal(true);
+ − 2211
QScriptValue val = qScriptValueFromValue(&eng, in);
+ − 2212
QVERIFY(val.isRegExp());
3
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 2213
QEXPECT_FAIL("", "QTBUG-6136: JSC-based back-end doesn't preserve QRegExp::minimal (always false)", Continue);
0
+ − 2214
QCOMPARE(val.toRegExp().isMinimal(), in.isMinimal());
+ − 2215
}
+ − 2216
}
+ − 2217
+ − 2218
static QScriptValue __import__(QScriptContext *ctx, QScriptEngine *eng)
+ − 2219
{
+ − 2220
return eng->importExtension(ctx->argument(0).toString());
+ − 2221
}
+ − 2222
+ − 2223
void tst_QScriptEngine::importExtension()
+ − 2224
{
+ − 2225
QStringList libPaths = QCoreApplication::instance()->libraryPaths();
+ − 2226
QCoreApplication::instance()->setLibraryPaths(QStringList() << SRCDIR);
+ − 2227
+ − 2228
QStringList availableExtensions;
+ − 2229
{
+ − 2230
QScriptEngine eng;
+ − 2231
QVERIFY(eng.importedExtensions().isEmpty());
+ − 2232
QStringList ret = eng.availableExtensions();
+ − 2233
QCOMPARE(ret.size(), 4);
+ − 2234
QCOMPARE(ret.at(0), QString::fromLatin1("com"));
+ − 2235
QCOMPARE(ret.at(1), QString::fromLatin1("com.trolltech"));
+ − 2236
QCOMPARE(ret.at(2), QString::fromLatin1("com.trolltech.recursive"));
+ − 2237
QCOMPARE(ret.at(3), QString::fromLatin1("com.trolltech.syntaxerror"));
+ − 2238
availableExtensions = ret;
+ − 2239
}
+ − 2240
+ − 2241
// try to import something that doesn't exist
+ − 2242
{
+ − 2243
QScriptEngine eng;
+ − 2244
QScriptValue ret = eng.importExtension("this.extension.does.not.exist");
+ − 2245
QCOMPARE(eng.hasUncaughtException(), true);
+ − 2246
QCOMPARE(ret.isError(), true);
+ − 2247
QCOMPARE(ret.toString(), QString::fromLatin1("Error: Unable to import this.extension.does.not.exist: no such extension"));
+ − 2248
}
+ − 2249
+ − 2250
{
+ − 2251
QScriptEngine eng;
+ − 2252
for (int x = 0; x < 2; ++x) {
+ − 2253
QCOMPARE(eng.globalObject().property("com").isValid(), x == 1);
+ − 2254
QScriptValue ret = eng.importExtension("com.trolltech");
+ − 2255
QCOMPARE(eng.hasUncaughtException(), false);
+ − 2256
QCOMPARE(ret.isUndefined(), true);
+ − 2257
+ − 2258
QScriptValue com = eng.globalObject().property("com");
+ − 2259
QCOMPARE(com.isObject(), true);
+ − 2260
QCOMPARE(com.property("wasDefinedAlready")
+ − 2261
.strictlyEquals(QScriptValue(&eng, false)), true);
+ − 2262
QCOMPARE(com.property("name")
+ − 2263
.strictlyEquals(QScriptValue(&eng, "com")), true);
+ − 2264
QCOMPARE(com.property("level")
+ − 2265
.strictlyEquals(QScriptValue(&eng, 1)), true);
+ − 2266
QVERIFY(com.property("originalPostInit").isUndefined());
+ − 2267
QVERIFY(com.property("postInitCallCount").strictlyEquals(1));
+ − 2268
+ − 2269
QScriptValue trolltech = com.property("trolltech");
+ − 2270
QCOMPARE(trolltech.isObject(), true);
+ − 2271
QCOMPARE(trolltech.property("wasDefinedAlready")
+ − 2272
.strictlyEquals(QScriptValue(&eng, false)), true);
+ − 2273
QCOMPARE(trolltech.property("name")
+ − 2274
.strictlyEquals(QScriptValue(&eng, "com.trolltech")), true);
+ − 2275
QCOMPARE(trolltech.property("level")
+ − 2276
.strictlyEquals(QScriptValue(&eng, 2)), true);
+ − 2277
QVERIFY(trolltech.property("originalPostInit").isUndefined());
+ − 2278
QVERIFY(trolltech.property("postInitCallCount").strictlyEquals(1));
+ − 2279
}
+ − 2280
QStringList imp = eng.importedExtensions();
+ − 2281
QCOMPARE(imp.size(), 2);
+ − 2282
QCOMPARE(imp.at(0), QString::fromLatin1("com"));
+ − 2283
QCOMPARE(imp.at(1), QString::fromLatin1("com.trolltech"));
+ − 2284
QCOMPARE(eng.availableExtensions(), availableExtensions);
+ − 2285
}
+ − 2286
+ − 2287
// recursive import should throw an error
+ − 2288
{
+ − 2289
QScriptEngine eng;
+ − 2290
QVERIFY(eng.importedExtensions().isEmpty());
+ − 2291
eng.globalObject().setProperty("__import__", eng.newFunction(__import__));
+ − 2292
QScriptValue ret = eng.importExtension("com.trolltech.recursive");
+ − 2293
QCOMPARE(eng.hasUncaughtException(), true);
+ − 2294
QVERIFY(ret.isError());
+ − 2295
QCOMPARE(ret.toString(), QString::fromLatin1("Error: recursive import of com.trolltech.recursive"));
+ − 2296
QStringList imp = eng.importedExtensions();
+ − 2297
QCOMPARE(imp.size(), 2);
+ − 2298
QCOMPARE(imp.at(0), QString::fromLatin1("com"));
+ − 2299
QCOMPARE(imp.at(1), QString::fromLatin1("com.trolltech"));
+ − 2300
QCOMPARE(eng.availableExtensions(), availableExtensions);
+ − 2301
}
+ − 2302
+ − 2303
{
+ − 2304
QScriptEngine eng;
+ − 2305
eng.globalObject().setProperty("__import__", eng.newFunction(__import__));
+ − 2306
for (int x = 0; x < 2; ++x) {
+ − 2307
if (x == 0)
+ − 2308
QVERIFY(eng.importedExtensions().isEmpty());
+ − 2309
QScriptValue ret = eng.importExtension("com.trolltech.syntaxerror");
+ − 2310
QVERIFY(eng.hasUncaughtException());
+ − 2311
QEXPECT_FAIL("", "JSC throws syntax error eagerly", Continue);
+ − 2312
QCOMPARE(eng.uncaughtExceptionLineNumber(), 4);
+ − 2313
QVERIFY(ret.isError());
+ − 2314
QCOMPARE(ret.property("message").toString(), QLatin1String("Parse error"));
+ − 2315
}
+ − 2316
QStringList imp = eng.importedExtensions();
+ − 2317
QCOMPARE(imp.size(), 2);
+ − 2318
QCOMPARE(imp.at(0), QString::fromLatin1("com"));
+ − 2319
QCOMPARE(imp.at(1), QString::fromLatin1("com.trolltech"));
+ − 2320
QCOMPARE(eng.availableExtensions(), availableExtensions);
+ − 2321
}
+ − 2322
+ − 2323
QCoreApplication::instance()->setLibraryPaths(libPaths);
+ − 2324
}
+ − 2325
+ − 2326
static QScriptValue recurse(QScriptContext *ctx, QScriptEngine *eng)
+ − 2327
{
+ − 2328
Q_UNUSED(eng);
+ − 2329
return ctx->callee().call();
+ − 2330
}
+ − 2331
+ − 2332
static QScriptValue recurse2(QScriptContext *ctx, QScriptEngine *eng)
+ − 2333
{
+ − 2334
Q_UNUSED(eng);
+ − 2335
return ctx->callee().construct();
+ − 2336
}
+ − 2337
+ − 2338
void tst_QScriptEngine::infiniteRecursion()
+ − 2339
{
+ − 2340
const QString stackOverflowError = QString::fromLatin1("RangeError: Maximum call stack size exceeded.");
+ − 2341
QScriptEngine eng;
+ − 2342
{
+ − 2343
QScriptValue ret = eng.evaluate("function foo() { foo(); }; foo();");
+ − 2344
QCOMPARE(ret.isError(), true);
+ − 2345
QCOMPARE(ret.toString(), stackOverflowError);
+ − 2346
}
+ − 2347
#if 0 //The native C++ stack overflow before the JS stack
+ − 2348
{
+ − 2349
QScriptValue fun = eng.newFunction(recurse);
+ − 2350
QScriptValue ret = fun.call();
+ − 2351
QCOMPARE(ret.isError(), true);
+ − 2352
QCOMPARE(ret.toString(), stackOverflowError);
+ − 2353
}
+ − 2354
{
+ − 2355
QScriptValue fun = eng.newFunction(recurse2);
+ − 2356
QScriptValue ret = fun.construct();
+ − 2357
QCOMPARE(ret.isError(), true);
+ − 2358
QCOMPARE(ret.toString(), stackOverflowError);
+ − 2359
}
+ − 2360
#endif
+ − 2361
}
+ − 2362
+ − 2363
struct Bar {
+ − 2364
int a;
+ − 2365
};
+ − 2366
+ − 2367
struct Baz : public Bar {
+ − 2368
int b;
+ − 2369
};
+ − 2370
+ − 2371
Q_DECLARE_METATYPE(Bar*)
+ − 2372
Q_DECLARE_METATYPE(Baz*)
+ − 2373
+ − 2374
Q_DECLARE_METATYPE(QGradient)
+ − 2375
Q_DECLARE_METATYPE(QGradient*)
+ − 2376
Q_DECLARE_METATYPE(QLinearGradient)
+ − 2377
+ − 2378
class Zoo : public QObject
+ − 2379
{
+ − 2380
Q_OBJECT
+ − 2381
public:
+ − 2382
Zoo() { }
+ − 2383
public slots:
+ − 2384
Baz *toBaz(Bar *b) { return reinterpret_cast<Baz*>(b); }
+ − 2385
};
+ − 2386
+ − 2387
void tst_QScriptEngine::castWithPrototypeChain()
+ − 2388
{
+ − 2389
QScriptEngine eng;
+ − 2390
Bar bar;
+ − 2391
Baz baz;
+ − 2392
QScriptValue barProto = qScriptValueFromValue(&eng, &bar);
+ − 2393
QScriptValue bazProto = qScriptValueFromValue(&eng, &baz);
+ − 2394
eng.setDefaultPrototype(qMetaTypeId<Bar*>(), barProto);
+ − 2395
eng.setDefaultPrototype(qMetaTypeId<Baz*>(), bazProto);
+ − 2396
+ − 2397
Baz baz2;
+ − 2398
baz2.a = 123;
+ − 2399
baz2.b = 456;
+ − 2400
QScriptValue baz2Value = qScriptValueFromValue(&eng, &baz2);
+ − 2401
{
+ − 2402
Baz *pbaz = qscriptvalue_cast<Baz*>(baz2Value);
+ − 2403
QVERIFY(pbaz != 0);
+ − 2404
QCOMPARE(pbaz->b, baz2.b);
+ − 2405
+ − 2406
Zoo zoo;
+ − 2407
QScriptValue scriptZoo = eng.newQObject(&zoo);
+ − 2408
QScriptValue toBaz = scriptZoo.property("toBaz");
+ − 2409
QVERIFY(toBaz.isFunction());
+ − 2410
+ − 2411
// no relation between Bar and Baz's proto --> casting fails
+ − 2412
{
+ − 2413
Bar *pbar = qscriptvalue_cast<Bar*>(baz2Value);
+ − 2414
QVERIFY(pbar == 0);
+ − 2415
}
+ − 2416
+ − 2417
{
+ − 2418
QScriptValue ret = toBaz.call(scriptZoo, QScriptValueList() << baz2Value);
+ − 2419
QVERIFY(ret.isError());
+ − 2420
QCOMPARE(ret.toString(), QLatin1String("TypeError: incompatible type of argument(s) in call to toBaz(); candidates were\n toBaz(Bar*)"));
+ − 2421
}
+ − 2422
+ − 2423
// establish chain -- now casting should work
+ − 2424
bazProto.setPrototype(barProto);
+ − 2425
+ − 2426
{
+ − 2427
Bar *pbar = qscriptvalue_cast<Bar*>(baz2Value);
+ − 2428
QVERIFY(pbar != 0);
+ − 2429
QCOMPARE(pbar->a, baz2.a);
+ − 2430
}
+ − 2431
+ − 2432
{
+ − 2433
QScriptValue ret = toBaz.call(scriptZoo, QScriptValueList() << baz2Value);
+ − 2434
QVERIFY(!ret.isError());
+ − 2435
QCOMPARE(qscriptvalue_cast<Baz*>(ret), pbaz);
+ − 2436
}
+ − 2437
}
+ − 2438
+ − 2439
bazProto.setPrototype(barProto.prototype()); // kill chain
+ − 2440
{
+ − 2441
Baz *pbaz = qscriptvalue_cast<Baz*>(baz2Value);
+ − 2442
QVERIFY(pbaz != 0);
+ − 2443
// should not work anymore
+ − 2444
Bar *pbar = qscriptvalue_cast<Bar*>(baz2Value);
+ − 2445
QVERIFY(pbar == 0);
+ − 2446
}
+ − 2447
+ − 2448
bazProto.setPrototype(eng.newQObject(this));
+ − 2449
{
+ − 2450
Baz *pbaz = qscriptvalue_cast<Baz*>(baz2Value);
+ − 2451
QVERIFY(pbaz != 0);
+ − 2452
// should not work now either
+ − 2453
Bar *pbar = qscriptvalue_cast<Bar*>(baz2Value);
+ − 2454
QVERIFY(pbar == 0);
+ − 2455
}
+ − 2456
+ − 2457
{
+ − 2458
QScriptValue b = qScriptValueFromValue(&eng, QBrush());
+ − 2459
b.setPrototype(barProto);
+ − 2460
// this shows that a "wrong" cast is possible, if you
+ − 2461
// don't play by the rules (the pointer is actually a QBrush*)...
+ − 2462
Bar *pbar = qscriptvalue_cast<Bar*>(b);
+ − 2463
QVERIFY(pbar != 0);
+ − 2464
}
+ − 2465
+ − 2466
{
+ − 2467
QScriptValue gradientProto = qScriptValueFromValue(&eng, QGradient());
+ − 2468
QScriptValue linearGradientProto = qScriptValueFromValue(&eng, QLinearGradient());
+ − 2469
linearGradientProto.setPrototype(gradientProto);
+ − 2470
QLinearGradient lg(10, 20, 30, 40);
+ − 2471
QScriptValue linearGradient = qScriptValueFromValue(&eng, lg);
+ − 2472
{
+ − 2473
QGradient *pgrad = qscriptvalue_cast<QGradient*>(linearGradient);
+ − 2474
QVERIFY(pgrad == 0);
+ − 2475
}
+ − 2476
linearGradient.setPrototype(linearGradientProto);
+ − 2477
{
+ − 2478
QGradient *pgrad = qscriptvalue_cast<QGradient*>(linearGradient);
+ − 2479
QVERIFY(pgrad != 0);
+ − 2480
QCOMPARE(pgrad->type(), QGradient::LinearGradient);
+ − 2481
QLinearGradient *plingrad = static_cast<QLinearGradient*>(pgrad);
+ − 2482
QCOMPARE(plingrad->start(), lg.start());
+ − 2483
QCOMPARE(plingrad->finalStop(), lg.finalStop());
+ − 2484
}
+ − 2485
}
+ − 2486
}
+ − 2487
+ − 2488
class Klazz : public QWidget,
+ − 2489
public QStandardItem,
+ − 2490
public QGraphicsItem
+ − 2491
{
+ − 2492
Q_OBJECT
+ − 2493
public:
+ − 2494
Klazz(QWidget *parent = 0) : QWidget(parent) { }
+ − 2495
virtual QRectF boundingRect() const { return QRectF(); }
+ − 2496
virtual void paint(QPainter*, const QStyleOptionGraphicsItem*, QWidget*) { }
+ − 2497
};
+ − 2498
+ − 2499
Q_DECLARE_METATYPE(Klazz*)
+ − 2500
Q_DECLARE_METATYPE(QStandardItem*)
+ − 2501
+ − 2502
void tst_QScriptEngine::castWithMultipleInheritance()
+ − 2503
{
+ − 2504
QScriptEngine eng;
+ − 2505
Klazz klz;
+ − 2506
QScriptValue v = eng.newQObject(&klz);
+ − 2507
+ − 2508
QCOMPARE(qscriptvalue_cast<Klazz*>(v), &klz);
+ − 2509
QCOMPARE(qscriptvalue_cast<QWidget*>(v), (QWidget *)&klz);
+ − 2510
QCOMPARE(qscriptvalue_cast<QObject*>(v), (QObject *)&klz);
+ − 2511
QCOMPARE(qscriptvalue_cast<QStandardItem*>(v), (QStandardItem *)&klz);
+ − 2512
QCOMPARE(qscriptvalue_cast<QGraphicsItem*>(v), (QGraphicsItem *)&klz);
+ − 2513
}
+ − 2514
+ − 2515
void tst_QScriptEngine::collectGarbage()
+ − 2516
{
+ − 2517
QScriptEngine eng;
+ − 2518
eng.evaluate("a = new Object(); a = new Object(); a = new Object()");
+ − 2519
QScriptValue a = eng.newObject();
+ − 2520
a = eng.newObject();
+ − 2521
a = eng.newObject();
+ − 2522
QPointer<QObject> ptr = new QObject();
+ − 2523
QVERIFY(ptr != 0);
+ − 2524
(void)eng.newQObject(ptr, QScriptEngine::ScriptOwnership);
+ − 2525
collectGarbage_helper(eng);
+ − 2526
QVERIFY(ptr == 0);
+ − 2527
}
+ − 2528
+ − 2529
void tst_QScriptEngine::gcWithNestedDataStructure()
+ − 2530
{
+ − 2531
QScriptEngine eng;
+ − 2532
eng.evaluate(
+ − 2533
"function makeList(size)"
+ − 2534
"{"
+ − 2535
" var head = { };"
+ − 2536
" var l = head;"
+ − 2537
" for (var i = 0; i < size; ++i) {"
+ − 2538
" l.data = i + \"\";"
+ − 2539
" l.next = { }; l = l.next;"
+ − 2540
" }"
+ − 2541
" l.next = null;"
+ − 2542
" return head;"
+ − 2543
"}");
+ − 2544
QCOMPARE(eng.hasUncaughtException(), false);
+ − 2545
const int size = 200;
+ − 2546
QScriptValue head = eng.evaluate(QString::fromLatin1("makeList(%0)").arg(size));
+ − 2547
QCOMPARE(eng.hasUncaughtException(), false);
+ − 2548
for (int x = 0; x < 2; ++x) {
+ − 2549
if (x == 1)
+ − 2550
eng.evaluate("gc()");
+ − 2551
QScriptValue l = head;
+ − 2552
for (int i = 0; i < 200; ++i) {
+ − 2553
QCOMPARE(l.property("data").toString(), QString::number(i));
+ − 2554
l = l.property("next");
+ − 2555
}
+ − 2556
}
+ − 2557
}
+ − 2558
+ − 2559
class EventReceiver : public QObject
+ − 2560
{
+ − 2561
public:
+ − 2562
EventReceiver() {
+ − 2563
received = false;
+ − 2564
}
+ − 2565
+ − 2566
bool event(QEvent *e) {
+ − 2567
received |= (e->type() == QEvent::User + 1);
+ − 2568
return QObject::event(e);
+ − 2569
}
+ − 2570
+ − 2571
bool received;
+ − 2572
};
+ − 2573
+ − 2574
void tst_QScriptEngine::processEventsWhileRunning()
+ − 2575
{
+ − 2576
for (int x = 0; x < 2; ++x) {
+ − 2577
QScriptEngine eng;
+ − 2578
if (x == 0)
+ − 2579
eng.pushContext();
+ − 2580
+ − 2581
QString script = QString::fromLatin1(
+ − 2582
"var end = Number(new Date()) + 2000;"
+ − 2583
"var x = 0;"
+ − 2584
"while (Number(new Date()) < end) {"
+ − 2585
" ++x;"
+ − 2586
"}");
+ − 2587
+ − 2588
EventReceiver receiver;
+ − 2589
QCoreApplication::postEvent(&receiver, new QEvent(QEvent::Type(QEvent::User+1)));
+ − 2590
+ − 2591
eng.evaluate(script);
+ − 2592
QVERIFY(!eng.hasUncaughtException());
+ − 2593
QVERIFY(!receiver.received);
+ − 2594
+ − 2595
QCOMPARE(eng.processEventsInterval(), -1);
+ − 2596
eng.setProcessEventsInterval(100);
+ − 2597
eng.evaluate(script);
+ − 2598
QVERIFY(!eng.hasUncaughtException());
+ − 2599
QVERIFY(receiver.received);
+ − 2600
+ − 2601
if (x == 0)
+ − 2602
eng.popContext();
+ − 2603
}
+ − 2604
}
+ − 2605
+ − 2606
class EventReceiver2 : public QObject
+ − 2607
{
+ − 2608
public:
+ − 2609
EventReceiver2(QScriptEngine *eng) {
+ − 2610
engine = eng;
+ − 2611
}
+ − 2612
+ − 2613
bool event(QEvent *e) {
+ − 2614
if (e->type() == QEvent::User + 1) {
+ − 2615
engine->currentContext()->throwError("Killed");
+ − 2616
}
+ − 2617
return QObject::event(e);
+ − 2618
}
+ − 2619
+ − 2620
QScriptEngine *engine;
+ − 2621
};
+ − 2622
+ − 2623
void tst_QScriptEngine::throwErrorFromProcessEvents()
+ − 2624
{
+ − 2625
QScriptEngine eng;
+ − 2626
+ − 2627
EventReceiver2 receiver(&eng);
+ − 2628
QCoreApplication::postEvent(&receiver, new QEvent(QEvent::Type(QEvent::User+1)));
+ − 2629
+ − 2630
eng.setProcessEventsInterval(100);
+ − 2631
QScriptValue ret = eng.evaluate(QString::fromLatin1("while (1) { }"));
+ − 2632
QVERIFY(ret.isError());
+ − 2633
QCOMPARE(ret.toString(), QString::fromLatin1("Error: Killed"));
+ − 2634
}
+ − 2635
+ − 2636
void tst_QScriptEngine::stacktrace()
+ − 2637
{
+ − 2638
QString script = QString::fromLatin1(
+ − 2639
"function foo(counter) {\n"
+ − 2640
" switch (counter) {\n"
+ − 2641
" case 0: foo(counter+1); break;\n"
+ − 2642
" case 1: foo(counter+1); break;\n"
+ − 2643
" case 2: foo(counter+1); break;\n"
+ − 2644
" case 3: foo(counter+1); break;\n"
+ − 2645
" case 4: foo(counter+1); break;\n"
+ − 2646
" default:\n"
+ − 2647
" throw new Error('blah');\n"
+ − 2648
" }\n"
+ − 2649
"}\n"
+ − 2650
"foo(0);");
+ − 2651
+ − 2652
const QString fileName("testfile");
+ − 2653
+ − 2654
QStringList backtrace;
+ − 2655
backtrace << "foo(5)@testfile:9"
+ − 2656
<< "foo(4)@testfile:7"
+ − 2657
<< "foo(3)@testfile:6"
+ − 2658
<< "foo(2)@testfile:5"
+ − 2659
<< "foo(1)@testfile:4"
+ − 2660
<< "foo(0)@testfile:3"
+ − 2661
<< "<global>()@testfile:12";
+ − 2662
+ − 2663
QScriptEngine eng;
+ − 2664
QScriptValue result = eng.evaluate(script, fileName);
+ − 2665
QVERIFY(eng.hasUncaughtException());
+ − 2666
QVERIFY(result.isError());
+ − 2667
3
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 2668
QEXPECT_FAIL("", "QTBUG-6139: uncaughtExceptionBacktrace() doesn't give the full backtrace", Abort);
0
+ − 2669
QCOMPARE(eng.uncaughtExceptionBacktrace(), backtrace);
+ − 2670
QVERIFY(eng.hasUncaughtException());
+ − 2671
QVERIFY(result.strictlyEquals(eng.uncaughtException()));
+ − 2672
+ − 2673
QCOMPARE(result.property("fileName").toString(), fileName);
+ − 2674
QCOMPARE(result.property("lineNumber").toInt32(), 9);
+ − 2675
+ − 2676
QScriptValue stack = result.property("stack");
+ − 2677
QVERIFY(stack.isArray());
+ − 2678
+ − 2679
QCOMPARE(stack.property("length").toInt32(), 7);
+ − 2680
+ − 2681
QScriptValueIterator it(stack);
+ − 2682
int counter = 5;
+ − 2683
while (it.hasNext()) {
+ − 2684
it.next();
+ − 2685
QScriptValue obj = it.value();
+ − 2686
QScriptValue frame = obj.property("frame");
+ − 2687
+ − 2688
QCOMPARE(obj.property("fileName").toString(), fileName);
+ − 2689
if (counter >= 0) {
+ − 2690
QScriptValue callee = frame.property("arguments").property("callee");
+ − 2691
QVERIFY(callee.strictlyEquals(eng.globalObject().property("foo")));
+ − 2692
QCOMPARE(obj.property("functionName").toString(), QString("foo"));
+ − 2693
int line = obj.property("lineNumber").toInt32();
+ − 2694
if (counter == 5)
+ − 2695
QCOMPARE(line, 9);
+ − 2696
else
+ − 2697
QCOMPARE(line, 3 + counter);
+ − 2698
} else {
+ − 2699
QVERIFY(frame.strictlyEquals(eng.globalObject()));
+ − 2700
QVERIFY(obj.property("functionName").toString().isEmpty());
+ − 2701
}
+ − 2702
+ − 2703
--counter;
+ − 2704
}
+ − 2705
+ − 2706
{
+ − 2707
QScriptValue bt = result.property("backtrace").call(result);
+ − 2708
QCOMPARE(qscriptvalue_cast<QStringList>(bt), backtrace);
+ − 2709
}
+ − 2710
+ − 2711
// throw something that isn't an Error object
+ − 2712
eng.clearExceptions();
+ − 2713
QVERIFY(eng.uncaughtExceptionBacktrace().isEmpty());
+ − 2714
QString script2 = QString::fromLatin1(
+ − 2715
"function foo(counter) {\n"
+ − 2716
" switch (counter) {\n"
+ − 2717
" case 0: foo(counter+1); break;\n"
+ − 2718
" case 1: foo(counter+1); break;\n"
+ − 2719
" case 2: foo(counter+1); break;\n"
+ − 2720
" case 3: foo(counter+1); break;\n"
+ − 2721
" case 4: foo(counter+1); break;\n"
+ − 2722
" default:\n"
+ − 2723
" throw 'just a string';\n"
+ − 2724
" }\n"
+ − 2725
"}\n"
+ − 2726
"foo(0);");
+ − 2727
+ − 2728
QScriptValue result2 = eng.evaluate(script2, fileName);
+ − 2729
QVERIFY(eng.hasUncaughtException());
+ − 2730
QVERIFY(!result2.isError());
+ − 2731
QVERIFY(result2.isString());
+ − 2732
+ − 2733
QCOMPARE(eng.uncaughtExceptionBacktrace(), backtrace);
+ − 2734
QVERIFY(eng.hasUncaughtException());
+ − 2735
+ − 2736
eng.clearExceptions();
+ − 2737
QVERIFY(!eng.hasUncaughtException());
+ − 2738
QVERIFY(eng.uncaughtExceptionBacktrace().isEmpty());
+ − 2739
}
+ − 2740
+ − 2741
void tst_QScriptEngine::numberParsing_data()
+ − 2742
{
+ − 2743
QTest::addColumn<QString>("string");
+ − 2744
QTest::addColumn<qsreal>("expect");
+ − 2745
+ − 2746
QTest::newRow("decimal 0") << QString("0") << qsreal(0);
+ − 2747
QTest::newRow("octal 0") << QString("00") << qsreal(00);
+ − 2748
QTest::newRow("hex 0") << QString("0x0") << qsreal(0x0);
+ − 2749
QTest::newRow("decimal 100") << QString("100") << qsreal(100);
+ − 2750
QTest::newRow("hex 100") << QString("0x100") << qsreal(0x100);
+ − 2751
QTest::newRow("octal 100") << QString("0100") << qsreal(0100);
+ − 2752
QTest::newRow("decimal 4G") << QString("4294967296") << qsreal(Q_UINT64_C(4294967296));
+ − 2753
QTest::newRow("hex 4G") << QString("0x100000000") << qsreal(Q_UINT64_C(0x100000000));
+ − 2754
QTest::newRow("octal 4G") << QString("040000000000") << qsreal(Q_UINT64_C(040000000000));
+ − 2755
QTest::newRow("0.5") << QString("0.5") << qsreal(0.5);
+ − 2756
QTest::newRow("1.5") << QString("1.5") << qsreal(1.5);
+ − 2757
QTest::newRow("1e2") << QString("1e2") << qsreal(100);
+ − 2758
}
+ − 2759
+ − 2760
void tst_QScriptEngine::numberParsing()
+ − 2761
{
+ − 2762
QFETCH(QString, string);
+ − 2763
QFETCH(qsreal, expect);
+ − 2764
+ − 2765
QScriptEngine eng;
+ − 2766
QScriptValue ret = eng.evaluate(string);
+ − 2767
QVERIFY(ret.isNumber());
+ − 2768
qsreal actual = ret.toNumber();
+ − 2769
QCOMPARE(actual, expect);
+ − 2770
}
+ − 2771
+ − 2772
// see ECMA-262, section 7.9
+ − 2773
void tst_QScriptEngine::automaticSemicolonInsertion()
+ − 2774
{
+ − 2775
QScriptEngine eng;
+ − 2776
{
+ − 2777
QScriptValue ret = eng.evaluate("{ 1 2 } 3");
+ − 2778
QVERIFY(ret.isError());
+ − 2779
QCOMPARE(ret.toString(), QString::fromLatin1("SyntaxError: Parse error"));
+ − 2780
}
+ − 2781
{
+ − 2782
QScriptValue ret = eng.evaluate("{ 1\n2 } 3");
+ − 2783
QVERIFY(ret.isNumber());
+ − 2784
QCOMPARE(ret.toInt32(), 3);
+ − 2785
}
+ − 2786
{
+ − 2787
QScriptValue ret = eng.evaluate("for (a; b\n)");
+ − 2788
QVERIFY(ret.isError());
+ − 2789
QCOMPARE(ret.toString(), QString::fromLatin1("SyntaxError: Parse error"));
+ − 2790
}
+ − 2791
{
+ − 2792
QScriptValue ret = eng.evaluate("(function() { return\n1 + 2 })()");
+ − 2793
QVERIFY(ret.isUndefined());
+ − 2794
}
+ − 2795
{
+ − 2796
eng.evaluate("c = 2; b = 1");
+ − 2797
QScriptValue ret = eng.evaluate("a = b\n++c");
+ − 2798
QVERIFY(ret.isNumber());
+ − 2799
QCOMPARE(ret.toInt32(), 3);
+ − 2800
}
+ − 2801
{
+ − 2802
QScriptValue ret = eng.evaluate("if (a > b)\nelse c = d");
+ − 2803
QVERIFY(ret.isError());
+ − 2804
QCOMPARE(ret.toString(), QString::fromLatin1("SyntaxError: Parse error"));
+ − 2805
}
+ − 2806
{
+ − 2807
eng.evaluate("function c() { return { foo: function() { return 5; } } }");
+ − 2808
eng.evaluate("b = 1; d = 2; e = 3");
+ − 2809
QScriptValue ret = eng.evaluate("a = b + c\n(d + e).foo()");
+ − 2810
QVERIFY(ret.isNumber());
+ − 2811
QCOMPARE(ret.toInt32(), 6);
+ − 2812
}
+ − 2813
{
+ − 2814
QScriptValue ret = eng.evaluate("throw\n1");
+ − 2815
QVERIFY(ret.isError());
+ − 2816
QCOMPARE(ret.toString(), QString::fromLatin1("SyntaxError: Parse error"));
+ − 2817
}
+ − 2818
{
+ − 2819
QScriptValue ret = eng.evaluate("a = Number(1)\n++a");
+ − 2820
QVERIFY(ret.isNumber());
+ − 2821
QCOMPARE(ret.toInt32(), 2);
+ − 2822
}
+ − 2823
+ − 2824
// "a semicolon is never inserted automatically if the semicolon
+ − 2825
// would then be parsed as an empty statement"
+ − 2826
{
+ − 2827
eng.evaluate("a = 123");
+ − 2828
QScriptValue ret = eng.evaluate("if (0)\n ++a; a");
+ − 2829
QVERIFY(ret.isNumber());
+ − 2830
QCOMPARE(ret.toInt32(), 123);
+ − 2831
}
+ − 2832
{
+ − 2833
eng.evaluate("a = 123");
+ − 2834
QScriptValue ret = eng.evaluate("if (0)\n --a; a");
+ − 2835
QVERIFY(ret.isNumber());
+ − 2836
QCOMPARE(ret.toInt32(), 123);
+ − 2837
}
+ − 2838
{
+ − 2839
eng.evaluate("a = 123");
+ − 2840
QScriptValue ret = eng.evaluate("if ((0))\n ++a; a");
+ − 2841
QVERIFY(ret.isNumber());
+ − 2842
QCOMPARE(ret.toInt32(), 123);
+ − 2843
}
+ − 2844
{
+ − 2845
eng.evaluate("a = 123");
+ − 2846
QScriptValue ret = eng.evaluate("if ((0))\n --a; a");
+ − 2847
QVERIFY(ret.isNumber());
+ − 2848
QCOMPARE(ret.toInt32(), 123);
+ − 2849
}
+ − 2850
{
+ − 2851
eng.evaluate("a = 123");
+ − 2852
QScriptValue ret = eng.evaluate("if (0\n)\n ++a; a");
+ − 2853
QVERIFY(ret.isNumber());
+ − 2854
QCOMPARE(ret.toInt32(), 123);
+ − 2855
}
+ − 2856
{
+ − 2857
eng.evaluate("a = 123");
+ − 2858
QScriptValue ret = eng.evaluate("if (0\n ++a; a");
+ − 2859
QVERIFY(ret.isError());
+ − 2860
}
+ − 2861
{
+ − 2862
eng.evaluate("a = 123");
+ − 2863
QScriptValue ret = eng.evaluate("if (0))\n ++a; a");
+ − 2864
QVERIFY(ret.isError());
+ − 2865
}
+ − 2866
{
+ − 2867
QScriptValue ret = eng.evaluate("n = 0; for (i = 0; i < 10; ++i)\n ++n; n");
+ − 2868
QVERIFY(ret.isNumber());
+ − 2869
QCOMPARE(ret.toInt32(), 10);
+ − 2870
}
+ − 2871
{
+ − 2872
QScriptValue ret = eng.evaluate("n = 30; for (i = 0; i < 10; ++i)\n --n; n");
+ − 2873
QVERIFY(ret.isNumber());
+ − 2874
QCOMPARE(ret.toInt32(), 20);
+ − 2875
}
+ − 2876
{
+ − 2877
QScriptValue ret = eng.evaluate("n = 0; for (var i = 0; i < 10; ++i)\n ++n; n");
+ − 2878
QVERIFY(ret.isNumber());
+ − 2879
QCOMPARE(ret.toInt32(), 10);
+ − 2880
}
+ − 2881
{
+ − 2882
QScriptValue ret = eng.evaluate("n = 30; for (var i = 0; i < 10; ++i)\n --n; n");
+ − 2883
QVERIFY(ret.isNumber());
+ − 2884
QCOMPARE(ret.toInt32(), 20);
+ − 2885
}
+ − 2886
{
+ − 2887
QScriptValue ret = eng.evaluate("n = 0; i = 0; while (i++ < 10)\n ++n; n");
+ − 2888
QVERIFY(ret.isNumber());
+ − 2889
QCOMPARE(ret.toInt32(), 10);
+ − 2890
}
+ − 2891
{
+ − 2892
QScriptValue ret = eng.evaluate("n = 30; i = 0; while (i++ < 10)\n --n; n");
+ − 2893
QVERIFY(ret.isNumber());
+ − 2894
QCOMPARE(ret.toInt32(), 20);
+ − 2895
}
+ − 2896
{
+ − 2897
QScriptValue ret = eng.evaluate("o = { a: 0, b: 1, c: 2 }; n = 0; for (i in o)\n ++n; n");
+ − 2898
QVERIFY(ret.isNumber());
+ − 2899
QCOMPARE(ret.toInt32(), 3);
+ − 2900
}
+ − 2901
{
+ − 2902
QScriptValue ret = eng.evaluate("o = { a: 0, b: 1, c: 2 }; n = 9; for (i in o)\n --n; n");
+ − 2903
QVERIFY(ret.isNumber());
+ − 2904
QCOMPARE(ret.toInt32(), 6);
+ − 2905
}
+ − 2906
{
+ − 2907
QScriptValue ret = eng.evaluate("o = { a: 0, b: 1, c: 2 }; n = 0; for (var i in o)\n ++n; n");
+ − 2908
QVERIFY(ret.isNumber());
+ − 2909
QCOMPARE(ret.toInt32(), 3);
+ − 2910
}
+ − 2911
{
+ − 2912
QScriptValue ret = eng.evaluate("o = { a: 0, b: 1, c: 2 }; n = 9; for (var i in o)\n --n; n");
+ − 2913
QVERIFY(ret.isNumber());
+ − 2914
QCOMPARE(ret.toInt32(), 6);
+ − 2915
}
+ − 2916
{
+ − 2917
QScriptValue ret = eng.evaluate("o = { n: 3 }; n = 5; with (o)\n ++n; n");
+ − 2918
QVERIFY(ret.isNumber());
+ − 2919
QCOMPARE(ret.toInt32(), 5);
+ − 2920
}
+ − 2921
{
+ − 2922
QScriptValue ret = eng.evaluate("o = { n: 3 }; n = 10; with (o)\n --n; n");
+ − 2923
QVERIFY(ret.isNumber());
+ − 2924
QCOMPARE(ret.toInt32(), 10);
+ − 2925
}
+ − 2926
{
+ − 2927
QScriptValue ret = eng.evaluate("n = 5; i = 0; do\n ++n; while (++i < 10); n");
+ − 2928
QVERIFY(ret.isNumber());
+ − 2929
QCOMPARE(ret.toInt32(), 15);
+ − 2930
}
+ − 2931
{
+ − 2932
QScriptValue ret = eng.evaluate("n = 20; i = 0; do\n --n; while (++i < 10); n");
+ − 2933
QVERIFY(ret.isNumber());
+ − 2934
QCOMPARE(ret.toInt32(), 10);
+ − 2935
}
+ − 2936
+ − 2937
{
+ − 2938
QScriptValue ret = eng.evaluate("n = 1; i = 0; if (n) i\n++n; n");
+ − 2939
QVERIFY(ret.isNumber());
+ − 2940
QCOMPARE(ret.toInt32(), 2);
+ − 2941
}
+ − 2942
{
+ − 2943
QScriptValue ret = eng.evaluate("n = 1; i = 0; if (n) i\n--n; n");
+ − 2944
QVERIFY(ret.isNumber());
+ − 2945
QCOMPARE(ret.toInt32(), 0);
+ − 2946
}
+ − 2947
+ − 2948
{
+ − 2949
QScriptValue ret = eng.evaluate("if (0)");
+ − 2950
QVERIFY(ret.isError());
+ − 2951
}
+ − 2952
{
+ − 2953
QScriptValue ret = eng.evaluate("while (0)");
+ − 2954
QVERIFY(ret.isError());
+ − 2955
}
+ − 2956
{
+ − 2957
QScriptValue ret = eng.evaluate("for (;;)");
+ − 2958
QVERIFY(ret.isError());
+ − 2959
}
+ − 2960
{
+ − 2961
QScriptValue ret = eng.evaluate("for (p in this)");
+ − 2962
QVERIFY(ret.isError());
+ − 2963
}
+ − 2964
{
+ − 2965
QScriptValue ret = eng.evaluate("with (this)");
+ − 2966
QVERIFY(ret.isError());
+ − 2967
}
+ − 2968
{
+ − 2969
QScriptValue ret = eng.evaluate("do");
+ − 2970
QVERIFY(ret.isError());
+ − 2971
}
+ − 2972
}
+ − 2973
+ − 2974
class EventReceiver3 : public QObject
+ − 2975
{
+ − 2976
public:
+ − 2977
enum AbortionResult {
+ − 2978
None = 0,
+ − 2979
String = 1,
+ − 2980
Error = 2
+ − 2981
};
+ − 2982
+ − 2983
EventReceiver3(QScriptEngine *eng) {
+ − 2984
engine = eng;
+ − 2985
resultType = None;
+ − 2986
}
+ − 2987
+ − 2988
bool event(QEvent *e) {
+ − 2989
if (e->type() == QEvent::User + 1) {
+ − 2990
switch (resultType) {
+ − 2991
case None:
+ − 2992
engine->abortEvaluation();
+ − 2993
break;
+ − 2994
case String:
+ − 2995
engine->abortEvaluation(QScriptValue(engine, QString::fromLatin1("Aborted")));
+ − 2996
break;
+ − 2997
case Error:
+ − 2998
engine->abortEvaluation(engine->currentContext()->throwError("AbortedWithError"));
+ − 2999
break;
+ − 3000
}
+ − 3001
}
+ − 3002
return QObject::event(e);
+ − 3003
}
+ − 3004
+ − 3005
AbortionResult resultType;
+ − 3006
QScriptEngine *engine;
+ − 3007
};
+ − 3008
+ − 3009
static QScriptValue myFunctionAbortingEvaluation(QScriptContext *, QScriptEngine *eng)
+ − 3010
{
+ − 3011
eng->abortEvaluation();
+ − 3012
return eng->nullValue(); // should be ignored
+ − 3013
}
+ − 3014
+ − 3015
void tst_QScriptEngine::abortEvaluation()
+ − 3016
{
+ − 3017
QScriptEngine eng;
+ − 3018
+ − 3019
eng.abortEvaluation();
+ − 3020
QVERIFY(!eng.hasUncaughtException());
+ − 3021
+ − 3022
eng.abortEvaluation(123);
+ − 3023
{
+ − 3024
QScriptValue ret = eng.evaluate("'ciao'");
+ − 3025
QVERIFY(ret.isString());
+ − 3026
QCOMPARE(ret.toString(), QString::fromLatin1("ciao"));
+ − 3027
}
+ − 3028
+ − 3029
EventReceiver3 receiver(&eng);
+ − 3030
+ − 3031
eng.setProcessEventsInterval(100);
+ − 3032
for (int x = 0; x < 3; ++x) {
+ − 3033
QCoreApplication::postEvent(&receiver, new QEvent(QEvent::Type(QEvent::User+1)));
+ − 3034
receiver.resultType = EventReceiver3::AbortionResult(x);
+ − 3035
QScriptValue ret = eng.evaluate(QString::fromLatin1("while (1) { }"));
+ − 3036
switch (receiver.resultType) {
+ − 3037
case EventReceiver3::None:
+ − 3038
QVERIFY(!eng.hasUncaughtException());
+ − 3039
QVERIFY(!ret.isValid());
+ − 3040
break;
+ − 3041
case EventReceiver3::String:
+ − 3042
QVERIFY(!eng.hasUncaughtException());
+ − 3043
QVERIFY(ret.isString());
+ − 3044
QCOMPARE(ret.toString(), QString::fromLatin1("Aborted"));
+ − 3045
break;
+ − 3046
case EventReceiver3::Error:
+ − 3047
QVERIFY(eng.hasUncaughtException());
+ − 3048
QVERIFY(ret.isError());
+ − 3049
QCOMPARE(ret.toString(), QString::fromLatin1("Error: AbortedWithError"));
+ − 3050
break;
+ − 3051
}
+ − 3052
}
+ − 3053
+ − 3054
// scripts cannot intercept the abortion with try/catch
+ − 3055
for (int y = 0; y < 3; ++y) {
+ − 3056
QCoreApplication::postEvent(&receiver, new QEvent(QEvent::Type(QEvent::User+1)));
+ − 3057
receiver.resultType = EventReceiver3::AbortionResult(y);
+ − 3058
QScriptValue ret = eng.evaluate(QString::fromLatin1(
+ − 3059
"while (1) {\n"
+ − 3060
" try {\n"
+ − 3061
" (function() { while (1) { } })();\n"
+ − 3062
" } catch (e) {\n"
+ − 3063
" ;\n"
+ − 3064
" }\n"
+ − 3065
"}"));
+ − 3066
switch (receiver.resultType) {
+ − 3067
case EventReceiver3::None:
+ − 3068
QVERIFY(!eng.hasUncaughtException());
+ − 3069
QVERIFY(!ret.isValid());
+ − 3070
break;
+ − 3071
case EventReceiver3::String:
+ − 3072
QVERIFY(!eng.hasUncaughtException());
+ − 3073
QVERIFY(ret.isString());
+ − 3074
QCOMPARE(ret.toString(), QString::fromLatin1("Aborted"));
+ − 3075
break;
+ − 3076
case EventReceiver3::Error:
+ − 3077
QVERIFY(eng.hasUncaughtException());
+ − 3078
QVERIFY(ret.isError());
+ − 3079
break;
+ − 3080
}
+ − 3081
}
+ − 3082
+ − 3083
{
+ − 3084
QScriptValue fun = eng.newFunction(myFunctionAbortingEvaluation);
+ − 3085
eng.globalObject().setProperty("myFunctionAbortingEvaluation", fun);
+ − 3086
QScriptValue ret = eng.evaluate("myFunctionAbortingEvaluation()");
+ − 3087
QVERIFY(!ret.isValid());
+ − 3088
}
+ − 3089
}
+ − 3090
+ − 3091
static QScriptValue myFunctionReturningIsEvaluating(QScriptContext *, QScriptEngine *eng)
+ − 3092
{
+ − 3093
return QScriptValue(eng, eng->isEvaluating());
+ − 3094
}
+ − 3095
+ − 3096
class EventReceiver4 : public QObject
+ − 3097
{
+ − 3098
public:
+ − 3099
EventReceiver4(QScriptEngine *eng) {
+ − 3100
engine = eng;
+ − 3101
wasEvaluating = false;
+ − 3102
}
+ − 3103
+ − 3104
bool event(QEvent *e) {
+ − 3105
if (e->type() == QEvent::User + 1) {
+ − 3106
wasEvaluating = engine->isEvaluating();
+ − 3107
}
+ − 3108
return QObject::event(e);
+ − 3109
}
+ − 3110
+ − 3111
QScriptEngine *engine;
+ − 3112
bool wasEvaluating;
+ − 3113
};
+ − 3114
+ − 3115
void tst_QScriptEngine::isEvaluating()
+ − 3116
{
+ − 3117
QScriptEngine eng;
+ − 3118
+ − 3119
QVERIFY(!eng.isEvaluating());
+ − 3120
+ − 3121
eng.evaluate("");
+ − 3122
QVERIFY(!eng.isEvaluating());
+ − 3123
eng.evaluate("123");
+ − 3124
QVERIFY(!eng.isEvaluating());
+ − 3125
eng.evaluate("0 = 0");
+ − 3126
QVERIFY(!eng.isEvaluating());
+ − 3127
+ − 3128
{
+ − 3129
QScriptValue fun = eng.newFunction(myFunctionReturningIsEvaluating);
+ − 3130
eng.globalObject().setProperty("myFunctionReturningIsEvaluating", fun);
+ − 3131
QScriptValue ret = eng.evaluate("myFunctionReturningIsEvaluating()");
+ − 3132
QVERIFY(ret.isBoolean());
+ − 3133
QVERIFY(ret.toBoolean());
+ − 3134
}
+ − 3135
+ − 3136
{
+ − 3137
EventReceiver4 receiver(&eng);
+ − 3138
QCoreApplication::postEvent(&receiver, new QEvent(QEvent::Type(QEvent::User+1)));
+ − 3139
+ − 3140
QString script = QString::fromLatin1(
+ − 3141
"var end = Number(new Date()) + 1000;"
+ − 3142
"var x = 0;"
+ − 3143
"while (Number(new Date()) < end) {"
+ − 3144
" ++x;"
+ − 3145
"}");
+ − 3146
+ − 3147
eng.setProcessEventsInterval(100);
+ − 3148
eng.evaluate(script);
+ − 3149
QVERIFY(receiver.wasEvaluating);
+ − 3150
}
+ − 3151
}
+ − 3152
+ − 3153
static QtMsgType theMessageType;
+ − 3154
static QString theMessage;
+ − 3155
+ − 3156
static void myMsgHandler(QtMsgType type, const char *msg)
+ − 3157
{
+ − 3158
theMessageType = type;
+ − 3159
theMessage = QString::fromLatin1(msg);
+ − 3160
}
+ − 3161
+ − 3162
void tst_QScriptEngine::printFunctionWithCustomHandler()
+ − 3163
{
+ − 3164
QScriptEngine eng;
+ − 3165
QtMsgHandler oldHandler = qInstallMsgHandler(myMsgHandler);
+ − 3166
QVERIFY(eng.globalObject().property("print").isFunction());
+ − 3167
theMessageType = QtSystemMsg;
+ − 3168
QVERIFY(theMessage.isEmpty());
+ − 3169
QVERIFY(eng.evaluate("print('test')").isUndefined());
+ − 3170
QCOMPARE(theMessageType, QtDebugMsg);
+ − 3171
QCOMPARE(theMessage, QString::fromLatin1("test"));
+ − 3172
theMessageType = QtSystemMsg;
+ − 3173
theMessage.clear();
+ − 3174
QVERIFY(eng.evaluate("print(3, true, 'little pigs')").isUndefined());
+ − 3175
QCOMPARE(theMessageType, QtDebugMsg);
+ − 3176
QCOMPARE(theMessage, QString::fromLatin1("3 true little pigs"));
+ − 3177
qInstallMsgHandler(oldHandler);
+ − 3178
}
+ − 3179
+ − 3180
void tst_QScriptEngine::printThrowsException()
+ − 3181
{
+ − 3182
QScriptEngine eng;
+ − 3183
QScriptValue ret = eng.evaluate("print({ toString: function() { throw 'foo'; } });");
+ − 3184
QVERIFY(eng.hasUncaughtException());
+ − 3185
QVERIFY(ret.strictlyEquals(QScriptValue(&eng, QLatin1String("foo"))));
+ − 3186
}
+ − 3187
+ − 3188
void tst_QScriptEngine::errorConstructors()
+ − 3189
{
+ − 3190
QScriptEngine eng;
+ − 3191
QStringList prefixes;
+ − 3192
prefixes << "" << "Eval" << "Range" << "Reference" << "Syntax" << "Type" << "URI";
+ − 3193
for (int x = 0; x < 3; ++x) {
+ − 3194
for (int i = 0; i < prefixes.size(); ++i) {
+ − 3195
QString name = prefixes.at(i) + QLatin1String("Error");
+ − 3196
QString code = QString(i+1, QLatin1Char('\n'));
+ − 3197
if (x == 0)
+ − 3198
code += QLatin1String("throw ");
+ − 3199
else if (x == 1)
+ − 3200
code += QLatin1String("new ");
+ − 3201
code += name + QLatin1String("()");
+ − 3202
QScriptValue ret = eng.evaluate(code);
+ − 3203
QVERIFY(ret.isError());
+ − 3204
QCOMPARE(eng.hasUncaughtException(), x == 0);
+ − 3205
eng.clearExceptions();
+ − 3206
QVERIFY(ret.toString().startsWith(name));
+ − 3207
if (x != 0)
3
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 3208
QEXPECT_FAIL("", "QTBUG-6138: JSC doesn't assign lineNumber when errors are not thrown", Continue);
0
+ − 3209
QCOMPARE(ret.property("lineNumber").toInt32(), i+2);
+ − 3210
}
+ − 3211
}
+ − 3212
}
+ − 3213
+ − 3214
static QScriptValue argumentsProperty_fun(QScriptContext *, QScriptEngine *eng)
+ − 3215
{
+ − 3216
eng->evaluate("var a = arguments[0];");
+ − 3217
eng->evaluate("arguments[0] = 200;");
+ − 3218
return eng->evaluate("a + arguments[0]");
+ − 3219
}
+ − 3220
+ − 3221
+ − 3222
void tst_QScriptEngine::argumentsProperty()
+ − 3223
{
+ − 3224
{
+ − 3225
QScriptEngine eng;
3
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 3226
{
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 3227
QScriptValue ret = eng.evaluate("arguments");
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 3228
QVERIFY(ret.isError());
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 3229
QCOMPARE(ret.toString(), QString::fromLatin1("ReferenceError: Can't find variable: arguments"));
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 3230
}
0
+ − 3231
eng.evaluate("arguments = 10");
3
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 3232
{
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 3233
QScriptValue ret = eng.evaluate("arguments");
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 3234
QVERIFY(ret.isNumber());
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 3235
QCOMPARE(ret.toInt32(), 10);
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 3236
}
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 3237
QVERIFY(eng.evaluate("delete arguments").toBoolean());
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 3238
QVERIFY(!eng.globalObject().property("arguments").isValid());
0
+ − 3239
}
+ − 3240
{
+ − 3241
QScriptEngine eng;
+ − 3242
eng.evaluate("o = { arguments: 123 }");
+ − 3243
QScriptValue ret = eng.evaluate("with (o) { arguments; }");
+ − 3244
QVERIFY(ret.isNumber());
+ − 3245
QCOMPARE(ret.toInt32(), 123);
+ − 3246
}
+ − 3247
{
+ − 3248
QScriptEngine eng;
3
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 3249
QVERIFY(!eng.globalObject().property("arguments").isValid());
0
+ − 3250
QScriptValue ret = eng.evaluate("(function() { arguments = 456; return arguments; })()");
+ − 3251
QVERIFY(ret.isNumber());
+ − 3252
QCOMPARE(ret.toInt32(), 456);
3
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 3253
QVERIFY(!eng.globalObject().property("arguments").isValid());
0
+ − 3254
}
+ − 3255
+ − 3256
{
+ − 3257
QScriptEngine eng;
+ − 3258
QScriptValue fun = eng.newFunction(argumentsProperty_fun);
+ − 3259
eng.globalObject().setProperty("fun", eng.newFunction(argumentsProperty_fun));
+ − 3260
QScriptValue result = eng.evaluate("fun(18)");
+ − 3261
QVERIFY(result.isNumber());
+ − 3262
QCOMPARE(result.toInt32(), 218);
+ − 3263
}
+ − 3264
}
+ − 3265
+ − 3266
void tst_QScriptEngine::numberClass()
+ − 3267
{
+ − 3268
QScriptEngine eng;
+ − 3269
+ − 3270
QScriptValue ctor = eng.globalObject().property("Number");
+ − 3271
QVERIFY(ctor.property("length").isNumber());
+ − 3272
QCOMPARE(ctor.property("length").toNumber(), qsreal(1));
+ − 3273
QScriptValue proto = ctor.property("prototype");
+ − 3274
QVERIFY(proto.isObject());
+ − 3275
{
+ − 3276
QScriptValue::PropertyFlags flags = QScriptValue::SkipInEnumeration
+ − 3277
| QScriptValue::Undeletable
+ − 3278
| QScriptValue::ReadOnly;
+ − 3279
QCOMPARE(ctor.propertyFlags("prototype"), flags);
+ − 3280
QVERIFY(ctor.property("MAX_VALUE").isNumber());
+ − 3281
QCOMPARE(ctor.propertyFlags("MAX_VALUE"), flags);
+ − 3282
QVERIFY(ctor.property("MIN_VALUE").isNumber());
+ − 3283
QCOMPARE(ctor.propertyFlags("MIN_VALUE"), flags);
+ − 3284
QVERIFY(ctor.property("NaN").isNumber());
+ − 3285
QCOMPARE(ctor.propertyFlags("NaN"), flags);
+ − 3286
QVERIFY(ctor.property("NEGATIVE_INFINITY").isNumber());
+ − 3287
QCOMPARE(ctor.propertyFlags("NEGATIVE_INFINITY"), flags);
+ − 3288
QVERIFY(ctor.property("POSITIVE_INFINITY").isNumber());
+ − 3289
QCOMPARE(ctor.propertyFlags("POSITIVE_INFINITY"), flags);
+ − 3290
}
+ − 3291
QVERIFY(proto.instanceOf(eng.globalObject().property("Object")));
+ − 3292
QCOMPARE(proto.toNumber(), qsreal(0));
+ − 3293
QVERIFY(proto.property("constructor").strictlyEquals(ctor));
+ − 3294
+ − 3295
{
+ − 3296
QScriptValue ret = eng.evaluate("Number()");
+ − 3297
QVERIFY(ret.isNumber());
+ − 3298
QCOMPARE(ret.toNumber(), qsreal(0));
+ − 3299
}
+ − 3300
{
+ − 3301
QScriptValue ret = eng.evaluate("Number(123)");
+ − 3302
QVERIFY(ret.isNumber());
+ − 3303
QCOMPARE(ret.toNumber(), qsreal(123));
+ − 3304
}
+ − 3305
{
+ − 3306
QScriptValue ret = eng.evaluate("Number('456')");
+ − 3307
QVERIFY(ret.isNumber());
+ − 3308
QCOMPARE(ret.toNumber(), qsreal(456));
+ − 3309
}
+ − 3310
{
+ − 3311
QScriptValue ret = eng.evaluate("new Number()");
+ − 3312
QVERIFY(!ret.isNumber());
+ − 3313
QVERIFY(ret.isObject());
+ − 3314
QCOMPARE(ret.toNumber(), qsreal(0));
+ − 3315
}
+ − 3316
{
+ − 3317
QScriptValue ret = eng.evaluate("new Number(123)");
+ − 3318
QVERIFY(!ret.isNumber());
+ − 3319
QVERIFY(ret.isObject());
+ − 3320
QCOMPARE(ret.toNumber(), qsreal(123));
+ − 3321
}
+ − 3322
{
+ − 3323
QScriptValue ret = eng.evaluate("new Number('456')");
+ − 3324
QVERIFY(!ret.isNumber());
+ − 3325
QVERIFY(ret.isObject());
+ − 3326
QCOMPARE(ret.toNumber(), qsreal(456));
+ − 3327
}
+ − 3328
+ − 3329
QVERIFY(proto.property("toString").isFunction());
+ − 3330
{
+ − 3331
QScriptValue ret = eng.evaluate("new Number(123).toString()");
+ − 3332
QVERIFY(ret.isString());
+ − 3333
QCOMPARE(ret.toString(), QString::fromLatin1("123"));
+ − 3334
}
+ − 3335
{
+ − 3336
QScriptValue ret = eng.evaluate("new Number(123).toString(8)");
+ − 3337
QVERIFY(ret.isString());
+ − 3338
QCOMPARE(ret.toString(), QString::fromLatin1("173"));
+ − 3339
}
+ − 3340
{
+ − 3341
QScriptValue ret = eng.evaluate("new Number(123).toString(16)");
+ − 3342
QVERIFY(ret.isString());
+ − 3343
QCOMPARE(ret.toString(), QString::fromLatin1("7b"));
+ − 3344
}
+ − 3345
QVERIFY(proto.property("toLocaleString").isFunction());
+ − 3346
{
+ − 3347
QScriptValue ret = eng.evaluate("new Number(123).toLocaleString()");
+ − 3348
QVERIFY(ret.isString());
+ − 3349
QCOMPARE(ret.toString(), QString::fromLatin1("123"));
+ − 3350
}
+ − 3351
QVERIFY(proto.property("valueOf").isFunction());
+ − 3352
{
+ − 3353
QScriptValue ret = eng.evaluate("new Number(123).valueOf()");
+ − 3354
QVERIFY(ret.isNumber());
+ − 3355
QCOMPARE(ret.toNumber(), qsreal(123));
+ − 3356
}
+ − 3357
QVERIFY(proto.property("toExponential").isFunction());
+ − 3358
{
+ − 3359
QScriptValue ret = eng.evaluate("new Number(123).toExponential()");
+ − 3360
QVERIFY(ret.isString());
+ − 3361
QCOMPARE(ret.toString(), QString::fromLatin1("1.23e+2"));
+ − 3362
}
+ − 3363
QVERIFY(proto.property("toFixed").isFunction());
+ − 3364
{
+ − 3365
QScriptValue ret = eng.evaluate("new Number(123).toFixed()");
+ − 3366
QVERIFY(ret.isString());
+ − 3367
QCOMPARE(ret.toString(), QString::fromLatin1("123"));
+ − 3368
}
+ − 3369
QVERIFY(proto.property("toPrecision").isFunction());
+ − 3370
{
+ − 3371
QScriptValue ret = eng.evaluate("new Number(123).toPrecision()");
+ − 3372
QVERIFY(ret.isString());
+ − 3373
QCOMPARE(ret.toString(), QString::fromLatin1("123"));
+ − 3374
}
+ − 3375
}
+ − 3376
+ − 3377
void tst_QScriptEngine::forInStatement()
+ − 3378
{
+ − 3379
QScriptEngine eng;
+ − 3380
{
+ − 3381
QScriptValue ret = eng.evaluate("o = { }; r = []; for (var p in o) r[r.length] = p; r");
+ − 3382
QStringList lst = qscriptvalue_cast<QStringList>(ret);
+ − 3383
QVERIFY(lst.isEmpty());
+ − 3384
}
+ − 3385
{
+ − 3386
QScriptValue ret = eng.evaluate("o = { p: 123 }; r = [];"
+ − 3387
"for (var p in o) r[r.length] = p; r");
+ − 3388
QStringList lst = qscriptvalue_cast<QStringList>(ret);
+ − 3389
QCOMPARE(lst.size(), 1);
+ − 3390
QCOMPARE(lst.at(0), QString::fromLatin1("p"));
+ − 3391
}
+ − 3392
{
+ − 3393
QScriptValue ret = eng.evaluate("o = { p: 123, q: 456 }; r = [];"
+ − 3394
"for (var p in o) r[r.length] = p; r");
+ − 3395
QStringList lst = qscriptvalue_cast<QStringList>(ret);
+ − 3396
QCOMPARE(lst.size(), 2);
+ − 3397
QCOMPARE(lst.at(0), QString::fromLatin1("p"));
+ − 3398
QCOMPARE(lst.at(1), QString::fromLatin1("q"));
+ − 3399
}
+ − 3400
+ − 3401
// properties in prototype
+ − 3402
{
+ − 3403
QScriptValue ret = eng.evaluate("o = { }; o.__proto__ = { p: 123 }; r = [];"
+ − 3404
"for (var p in o) r[r.length] = p; r");
+ − 3405
QStringList lst = qscriptvalue_cast<QStringList>(ret);
+ − 3406
QCOMPARE(lst.size(), 1);
+ − 3407
QCOMPARE(lst.at(0), QString::fromLatin1("p"));
+ − 3408
}
+ − 3409
{
+ − 3410
QScriptValue ret = eng.evaluate("o = { p: 123 }; o.__proto__ = { q: 456 }; r = [];"
+ − 3411
"for (var p in o) r[r.length] = p; r");
+ − 3412
QStringList lst = qscriptvalue_cast<QStringList>(ret);
+ − 3413
QCOMPARE(lst.size(), 2);
+ − 3414
QCOMPARE(lst.at(0), QString::fromLatin1("p"));
+ − 3415
QCOMPARE(lst.at(1), QString::fromLatin1("q"));
+ − 3416
}
+ − 3417
{
+ − 3418
// shadowed property
+ − 3419
QScriptValue ret = eng.evaluate("o = { p: 123 }; o.__proto__ = { p: 456 }; r = [];"
+ − 3420
"for (var p in o) r[r.length] = p; r");
+ − 3421
QStringList lst = qscriptvalue_cast<QStringList>(ret);
+ − 3422
QCOMPARE(lst.size(), 1);
+ − 3423
QCOMPARE(lst.at(0), QString::fromLatin1("p"));
+ − 3424
}
+ − 3425
+ − 3426
// deleting property during enumeration
+ − 3427
{
+ − 3428
QScriptValue ret = eng.evaluate("o = { p: 123 }; r = [];"
+ − 3429
"for (var p in o) { r[r.length] = p; delete r[p]; } r");
+ − 3430
QStringList lst = qscriptvalue_cast<QStringList>(ret);
+ − 3431
QCOMPARE(lst.size(), 1);
+ − 3432
QCOMPARE(lst.at(0), QString::fromLatin1("p"));
+ − 3433
}
+ − 3434
{
+ − 3435
QScriptValue ret = eng.evaluate("o = { p: 123, q: 456 }; r = [];"
+ − 3436
"for (var p in o) { r[r.length] = p; delete o.q; } r");
+ − 3437
QStringList lst = qscriptvalue_cast<QStringList>(ret);
+ − 3438
QCOMPARE(lst.size(), 1);
+ − 3439
QCOMPARE(lst.at(0), QString::fromLatin1("p"));
+ − 3440
}
+ − 3441
+ − 3442
// adding property during enumeration
+ − 3443
{
+ − 3444
QScriptValue ret = eng.evaluate("o = { p: 123 }; r = [];"
+ − 3445
"for (var p in o) { r[r.length] = p; o.q = 456; } r");
+ − 3446
QStringList lst = qscriptvalue_cast<QStringList>(ret);
+ − 3447
QCOMPARE(lst.size(), 1);
+ − 3448
QCOMPARE(lst.at(0), QString::fromLatin1("p"));
+ − 3449
}
+ − 3450
+ − 3451
// arrays
+ − 3452
{
+ − 3453
QScriptValue ret = eng.evaluate("a = [123, 456]; r = [];"
+ − 3454
"for (var p in a) r[r.length] = p; r");
+ − 3455
QStringList lst = qscriptvalue_cast<QStringList>(ret);
+ − 3456
QCOMPARE(lst.size(), 2);
+ − 3457
QCOMPARE(lst.at(0), QString::fromLatin1("0"));
+ − 3458
QCOMPARE(lst.at(1), QString::fromLatin1("1"));
+ − 3459
}
+ − 3460
{
+ − 3461
QScriptValue ret = eng.evaluate("a = [123, 456]; a.foo = 'bar'; r = [];"
+ − 3462
"for (var p in a) r[r.length] = p; r");
+ − 3463
QStringList lst = qscriptvalue_cast<QStringList>(ret);
+ − 3464
QCOMPARE(lst.size(), 3);
+ − 3465
QCOMPARE(lst.at(0), QString::fromLatin1("0"));
+ − 3466
QCOMPARE(lst.at(1), QString::fromLatin1("1"));
+ − 3467
QCOMPARE(lst.at(2), QString::fromLatin1("foo"));
+ − 3468
}
+ − 3469
{
+ − 3470
QScriptValue ret = eng.evaluate("a = [123, 456]; a.foo = 'bar';"
+ − 3471
"b = [111, 222, 333]; b.bar = 'baz';"
+ − 3472
"a.__proto__ = b; r = [];"
+ − 3473
"for (var p in a) r[r.length] = p; r");
+ − 3474
QStringList lst = qscriptvalue_cast<QStringList>(ret);
+ − 3475
QCOMPARE(lst.size(), 5);
+ − 3476
QCOMPARE(lst.at(0), QString::fromLatin1("0"));
+ − 3477
QCOMPARE(lst.at(1), QString::fromLatin1("1"));
+ − 3478
QCOMPARE(lst.at(2), QString::fromLatin1("foo"));
+ − 3479
QCOMPARE(lst.at(3), QString::fromLatin1("2"));
+ − 3480
QCOMPARE(lst.at(4), QString::fromLatin1("bar"));
+ − 3481
}
+ − 3482
+ − 3483
// null and undefined
+ − 3484
// according to the spec, we should throw an exception; however, for
+ − 3485
// compability with the real world, we don't
+ − 3486
{
+ − 3487
QScriptValue ret = eng.evaluate("r = true; for (var p in undefined) r = false; r");
+ − 3488
QVERIFY(ret.isBool());
+ − 3489
QVERIFY(ret.toBool());
+ − 3490
}
+ − 3491
{
+ − 3492
QScriptValue ret = eng.evaluate("r = true; for (var p in null) r = false; r");
+ − 3493
QVERIFY(ret.isBool());
+ − 3494
QVERIFY(ret.toBool());
+ − 3495
}
+ − 3496
}
+ − 3497
+ − 3498
void tst_QScriptEngine::functionExpression()
+ − 3499
{
+ − 3500
// task 175679
+ − 3501
QScriptEngine eng;
+ − 3502
QVERIFY(!eng.globalObject().property("bar").isValid());
+ − 3503
eng.evaluate("function foo(arg) {\n"
+ − 3504
" if (arg == 'bar')\n"
+ − 3505
" function bar() { return 'bar'; }\n"
+ − 3506
" else\n"
+ − 3507
" function baz() { return 'baz'; }\n"
+ − 3508
" return (arg == 'bar') ? bar : baz;\n"
+ − 3509
"}");
+ − 3510
QVERIFY(!eng.globalObject().property("bar").isValid());
+ − 3511
QVERIFY(!eng.globalObject().property("baz").isValid());
+ − 3512
QVERIFY(eng.evaluate("foo").isFunction());
+ − 3513
{
+ − 3514
QScriptValue ret = eng.evaluate("foo('bar')");
+ − 3515
QVERIFY(ret.isFunction());
+ − 3516
QScriptValue ret2 = ret.call(QScriptValue());
+ − 3517
QCOMPARE(ret2.toString(), QString::fromLatin1("bar"));
+ − 3518
QVERIFY(!eng.globalObject().property("bar").isValid());
+ − 3519
QVERIFY(!eng.globalObject().property("baz").isValid());
+ − 3520
}
+ − 3521
{
+ − 3522
QScriptValue ret = eng.evaluate("foo('baz')");
+ − 3523
QVERIFY(ret.isFunction());
+ − 3524
QScriptValue ret2 = ret.call(QScriptValue());
+ − 3525
QCOMPARE(ret2.toString(), QString::fromLatin1("baz"));
+ − 3526
QVERIFY(!eng.globalObject().property("bar").isValid());
+ − 3527
QVERIFY(!eng.globalObject().property("baz").isValid());
+ − 3528
}
+ − 3529
}
+ − 3530
+ − 3531
void tst_QScriptEngine::stringObjects()
+ − 3532
{
+ − 3533
QScriptEngine eng;
+ − 3534
QString str("ciao");
+ − 3535
// in C++
+ − 3536
{
+ − 3537
QScriptValue obj = QScriptValue(&eng, str).toObject();
+ − 3538
QCOMPARE(obj.property("length").toInt32(), str.length());
+ − 3539
QCOMPARE(obj.propertyFlags("length"), QScriptValue::PropertyFlags(QScriptValue::Undeletable | QScriptValue::SkipInEnumeration | QScriptValue::ReadOnly));
+ − 3540
for (int i = 0; i < str.length(); ++i) {
+ − 3541
QString pname = QString::number(i);
+ − 3542
QVERIFY(obj.property(pname).isString());
+ − 3543
QCOMPARE(obj.property(pname).toString(), QString(str.at(i)));
+ − 3544
QCOMPARE(obj.propertyFlags(pname), QScriptValue::PropertyFlags(QScriptValue::Undeletable | QScriptValue::ReadOnly));
+ − 3545
obj.setProperty(pname, QScriptValue());
+ − 3546
obj.setProperty(pname, QScriptValue(&eng, 123));
+ − 3547
QVERIFY(obj.property(pname).isString());
+ − 3548
QCOMPARE(obj.property(pname).toString(), QString(str.at(i)));
+ − 3549
}
+ − 3550
QVERIFY(!obj.property("-1").isValid());
+ − 3551
QVERIFY(!obj.property(QString::number(str.length())).isValid());
+ − 3552
+ − 3553
QScriptValue val(&eng, 123);
+ − 3554
obj.setProperty("-1", val);
+ − 3555
QVERIFY(obj.property("-1").strictlyEquals(val));
+ − 3556
obj.setProperty("100", val);
+ − 3557
QVERIFY(obj.property("100").strictlyEquals(val));
+ − 3558
}
+ − 3559
+ − 3560
// in script
+ − 3561
{
+ − 3562
QScriptValue ret = eng.evaluate("s = new String('ciao'); r = []; for (var p in s) r.push(p); r");
+ − 3563
QVERIFY(ret.isArray());
+ − 3564
QStringList lst = qscriptvalue_cast<QStringList>(ret);
+ − 3565
QCOMPARE(lst.size(), str.length());
+ − 3566
for (int i = 0; i < str.length(); ++i)
+ − 3567
QCOMPARE(lst.at(i), QString::number(i));
+ − 3568
+ − 3569
QScriptValue ret2 = eng.evaluate("s[0] = 123; s[0]");
+ − 3570
QVERIFY(ret2.isString());
+ − 3571
QCOMPARE(ret2.toString().length(), 1);
+ − 3572
QCOMPARE(ret2.toString().at(0), str.at(0));
+ − 3573
+ − 3574
QScriptValue ret3 = eng.evaluate("s[-1] = 123; s[-1]");
+ − 3575
QVERIFY(ret3.isNumber());
+ − 3576
QCOMPARE(ret3.toInt32(), 123);
+ − 3577
+ − 3578
QScriptValue ret4 = eng.evaluate("s[s.length] = 456; s[s.length]");
+ − 3579
QVERIFY(ret4.isNumber());
+ − 3580
QCOMPARE(ret4.toInt32(), 456);
+ − 3581
+ − 3582
QScriptValue ret5 = eng.evaluate("delete s[0]");
+ − 3583
QVERIFY(ret5.isBoolean());
+ − 3584
QVERIFY(!ret5.toBoolean());
+ − 3585
+ − 3586
QScriptValue ret6 = eng.evaluate("delete s[-1]");
+ − 3587
QVERIFY(ret6.isBoolean());
+ − 3588
QVERIFY(ret6.toBoolean());
+ − 3589
+ − 3590
QScriptValue ret7 = eng.evaluate("delete s[s.length]");
+ − 3591
QVERIFY(ret7.isBoolean());
+ − 3592
QVERIFY(ret7.toBoolean());
+ − 3593
}
+ − 3594
+ − 3595
// task 212440
+ − 3596
{
+ − 3597
QScriptValue ret = eng.evaluate("replace_args = []; \"a a a\".replace(/(a)/g, function() { replace_args.push(arguments); }); replace_args");
+ − 3598
QVERIFY(ret.isArray());
+ − 3599
int len = ret.property("length").toInt32();
+ − 3600
QCOMPARE(len, 3);
+ − 3601
for (int i = 0; i < len; ++i) {
+ − 3602
QScriptValue args = ret.property(i);
+ − 3603
QCOMPARE(args.property("length").toInt32(), 4);
+ − 3604
QCOMPARE(args.property(0).toString(), QString::fromLatin1("a")); // matched string
+ − 3605
QCOMPARE(args.property(1).toString(), QString::fromLatin1("a")); // capture
+ − 3606
QVERIFY(args.property(2).isNumber());
+ − 3607
QCOMPARE(args.property(2).toInt32(), i*2); // index of match
+ − 3608
QCOMPARE(args.property(3).toString(), QString::fromLatin1("a a a"));
+ − 3609
}
+ − 3610
}
+ − 3611
// task 212501
+ − 3612
{
+ − 3613
QScriptValue ret = eng.evaluate("\"foo\".replace(/a/g, function() {})");
+ − 3614
QVERIFY(ret.isString());
+ − 3615
QCOMPARE(ret.toString(), QString::fromLatin1("foo"));
+ − 3616
}
+ − 3617
}
+ − 3618
+ − 3619
void tst_QScriptEngine::getterSetterThisObject()
+ − 3620
{
+ − 3621
// Global Object
+ − 3622
{
+ − 3623
QScriptEngine eng;
+ − 3624
// read
+ − 3625
eng.evaluate("__defineGetter__('x', function() { return this; });");
+ − 3626
{
+ − 3627
QScriptValue ret = eng.evaluate("x");
+ − 3628
QVERIFY(ret.equals(eng.globalObject()));
+ − 3629
}
+ − 3630
{
+ − 3631
QScriptValue ret = eng.evaluate("(function() { return x; })()");
+ − 3632
QVERIFY(ret.equals(eng.globalObject()));
+ − 3633
}
+ − 3634
{
+ − 3635
QScriptValue ret = eng.evaluate("with (this) x");
+ − 3636
QVERIFY(ret.equals(eng.globalObject()));
+ − 3637
}
+ − 3638
{
+ − 3639
QScriptValue ret = eng.evaluate("with ({}) x");
+ − 3640
QVERIFY(ret.equals(eng.globalObject()));
+ − 3641
}
+ − 3642
{
+ − 3643
QScriptValue ret = eng.evaluate("(function() { with ({}) return x; })()");
+ − 3644
QVERIFY(ret.equals(eng.globalObject()));
+ − 3645
}
+ − 3646
// write
+ − 3647
eng.evaluate("__defineSetter__('x', function() { return this; });");
+ − 3648
{
+ − 3649
QScriptValue ret = eng.evaluate("x = 'foo'");
+ − 3650
// SpiderMonkey says setter return value, JSC says RHS.
+ − 3651
QVERIFY(ret.isString());
+ − 3652
QCOMPARE(ret.toString(), QString::fromLatin1("foo"));
+ − 3653
}
+ − 3654
{
+ − 3655
QScriptValue ret = eng.evaluate("(function() { return x = 'foo'; })()");
+ − 3656
// SpiderMonkey says setter return value, JSC says RHS.
+ − 3657
QVERIFY(ret.isString());
+ − 3658
QCOMPARE(ret.toString(), QString::fromLatin1("foo"));
+ − 3659
}
+ − 3660
{
+ − 3661
QScriptValue ret = eng.evaluate("with (this) x = 'foo'");
+ − 3662
// SpiderMonkey says setter return value, JSC says RHS.
+ − 3663
QVERIFY(ret.isString());
+ − 3664
QCOMPARE(ret.toString(), QString::fromLatin1("foo"));
+ − 3665
}
+ − 3666
{
+ − 3667
QScriptValue ret = eng.evaluate("with ({}) x = 'foo'");
+ − 3668
// SpiderMonkey says setter return value, JSC says RHS.
+ − 3669
QVERIFY(ret.isString());
+ − 3670
QCOMPARE(ret.toString(), QString::fromLatin1("foo"));
+ − 3671
}
+ − 3672
{
+ − 3673
QScriptValue ret = eng.evaluate("(function() { with ({}) return x = 'foo'; })()");
+ − 3674
// SpiderMonkey says setter return value, JSC says RHS.
+ − 3675
QVERIFY(ret.isString());
+ − 3676
QCOMPARE(ret.toString(), QString::fromLatin1("foo"));
+ − 3677
}
+ − 3678
}
+ − 3679
+ − 3680
// other object
+ − 3681
{
+ − 3682
QScriptEngine eng;
+ − 3683
eng.evaluate("o = {}");
+ − 3684
// read
+ − 3685
eng.evaluate("o.__defineGetter__('x', function() { return this; })");
+ − 3686
QVERIFY(eng.evaluate("o.x === o").toBoolean());
+ − 3687
QVERIFY(eng.evaluate("with (o) x").equals(eng.evaluate("o")));
+ − 3688
QVERIFY(eng.evaluate("(function() { with (o) return x; })() === o").toBoolean());
+ − 3689
eng.evaluate("q = {}; with (o) with (q) x").equals(eng.evaluate("o"));
+ − 3690
// write
+ − 3691
eng.evaluate("o.__defineSetter__('x', function() { return this; });");
+ − 3692
// SpiderMonkey says setter return value, JSC says RHS.
+ − 3693
QVERIFY(eng.evaluate("(o.x = 'foo') === 'foo'").toBoolean());
+ − 3694
QVERIFY(eng.evaluate("with (o) x = 'foo'").equals("foo"));
+ − 3695
QVERIFY(eng.evaluate("with (o) with (q) x = 'foo'").equals("foo"));
+ − 3696
}
+ − 3697
+ − 3698
// getter+setter in prototype chain
+ − 3699
{
+ − 3700
QScriptEngine eng;
+ − 3701
eng.evaluate("o = {}; p = {}; o.__proto__ = p");
+ − 3702
// read
+ − 3703
eng.evaluate("p.__defineGetter__('x', function() { return this; })");
+ − 3704
QVERIFY(eng.evaluate("o.x === o").toBoolean());
+ − 3705
QVERIFY(eng.evaluate("with (o) x").equals(eng.evaluate("o")));
+ − 3706
QVERIFY(eng.evaluate("(function() { with (o) return x; })() === o").toBoolean());
+ − 3707
eng.evaluate("q = {}; with (o) with (q) x").equals(eng.evaluate("o"));
+ − 3708
eng.evaluate("with (q) with (o) x").equals(eng.evaluate("o"));
+ − 3709
// write
+ − 3710
eng.evaluate("o.__defineSetter__('x', function() { return this; });");
+ − 3711
// SpiderMonkey says setter return value, JSC says RHS.
+ − 3712
QVERIFY(eng.evaluate("(o.x = 'foo') === 'foo'").toBoolean());
+ − 3713
QVERIFY(eng.evaluate("with (o) x = 'foo'").equals("foo"));
+ − 3714
QVERIFY(eng.evaluate("with (o) with (q) x = 'foo'").equals("foo"));
+ − 3715
}
+ − 3716
+ − 3717
// getter+setter in activation
+ − 3718
{
+ − 3719
QScriptEngine eng;
+ − 3720
QScriptContext *ctx = eng.pushContext();
+ − 3721
QVERIFY(ctx != 0);
+ − 3722
QScriptValue act = ctx->activationObject();
+ − 3723
act.setProperty("act", act);
+ − 3724
// read
+ − 3725
eng.evaluate("act.__defineGetter__('x', function() { return this; })");
+ − 3726
QVERIFY(eng.evaluate("x === act").toBoolean());
+ − 3727
QEXPECT_FAIL("", "Exotic overload (don't care for now)", Continue);
+ − 3728
QVERIFY(eng.evaluate("with (act) x").equals("foo"));
+ − 3729
QVERIFY(eng.evaluate("(function() { with (act) return x; })() === act").toBoolean());
+ − 3730
eng.evaluate("q = {}; with (act) with (q) x").equals(eng.evaluate("act"));
+ − 3731
eng.evaluate("with (q) with (act) x").equals(eng.evaluate("act"));
+ − 3732
// write
+ − 3733
eng.evaluate("act.__defineSetter__('x', function() { return this; });");
+ − 3734
QVERIFY(eng.evaluate("(x = 'foo') === 'foo'").toBoolean());
+ − 3735
QVERIFY(eng.evaluate("with (act) x = 'foo'").equals("foo"));
+ − 3736
QVERIFY(eng.evaluate("with (act) with (q) x = 'foo'").equals("foo"));
+ − 3737
eng.popContext();
+ − 3738
}
+ − 3739
}
+ − 3740
+ − 3741
void tst_QScriptEngine::continueInSwitch()
+ − 3742
{
+ − 3743
QScriptEngine eng;
+ − 3744
// switch - continue
+ − 3745
{
+ − 3746
QScriptValue ret = eng.evaluate("switch (1) { default: continue; }");
+ − 3747
QVERIFY(ret.isError());
+ − 3748
}
+ − 3749
// for - switch - case - continue
+ − 3750
{
+ − 3751
QScriptValue ret = eng.evaluate("j = 0; for (i = 0; i < 100000; ++i) {\n"
+ − 3752
" switch (i) {\n"
+ − 3753
" case 1: ++j; continue;\n"
+ − 3754
" case 100: ++j; continue;\n"
+ − 3755
" case 1000: ++j; continue;\n"
+ − 3756
" }\n"
+ − 3757
"}; j");
+ − 3758
QVERIFY(ret.isNumber());
+ − 3759
QCOMPARE(ret.toInt32(), 3);
+ − 3760
}
+ − 3761
// for - switch - case - default - continue
+ − 3762
{
+ − 3763
QScriptValue ret = eng.evaluate("j = 0; for (i = 0; i < 100000; ++i) {\n"
+ − 3764
" switch (i) {\n"
+ − 3765
" case 1: ++j; continue;\n"
+ − 3766
" case 100: ++j; continue;\n"
+ − 3767
" case 1000: ++j; continue;\n"
+ − 3768
" default: if (i < 50000) break; else continue;\n"
+ − 3769
" }\n"
+ − 3770
"}; j");
+ − 3771
QVERIFY(ret.isNumber());
+ − 3772
QCOMPARE(ret.toInt32(), 3);
+ − 3773
}
+ − 3774
// switch - for - continue
+ − 3775
{
+ − 3776
QScriptValue ret = eng.evaluate("j = 123; switch (j) {\n"
+ − 3777
" case 123:\n"
+ − 3778
" for (i = 0; i < 100000; ++i) {\n"
+ − 3779
" continue;\n"
+ − 3780
" }\n"
+ − 3781
"}; i\n");
+ − 3782
QVERIFY(ret.isNumber());
+ − 3783
QCOMPARE(ret.toInt32(), 100000);
+ − 3784
}
+ − 3785
// switch - switch - continue
+ − 3786
{
+ − 3787
QScriptValue ret = eng.evaluate("i = 1; switch (i) { default: switch (i) { case 1: continue; } }");
+ − 3788
QVERIFY(ret.isError());
+ − 3789
}
+ − 3790
// for - switch - switch - continue
+ − 3791
{
+ − 3792
QScriptValue ret = eng.evaluate("j = 0; for (i = 0; i < 100000; ++i) {\n"
+ − 3793
" switch (i) {\n"
+ − 3794
" case 1:\n"
+ − 3795
" switch (i) {\n"
+ − 3796
" case 1: ++j; continue;\n"
+ − 3797
" }\n"
+ − 3798
" }\n"
+ − 3799
"}; j");
+ − 3800
QVERIFY(ret.isNumber());
+ − 3801
QCOMPARE(ret.toInt32(), 1);
+ − 3802
}
+ − 3803
// switch - for - switch - continue
+ − 3804
{
+ − 3805
QScriptValue ret = eng.evaluate("j = 123; switch (j) {\n"
+ − 3806
" case 123:\n"
+ − 3807
" for (i = 0; i < 100000; ++i) {\n"
+ − 3808
" switch (i) {\n"
+ − 3809
" case 1:\n"
+ − 3810
" ++j; continue;\n"
+ − 3811
" }\n"
+ − 3812
" }\n"
+ − 3813
"}; i\n");
+ − 3814
QVERIFY(ret.isNumber());
+ − 3815
QCOMPARE(ret.toInt32(), 100000);
+ − 3816
}
+ − 3817
}
+ − 3818
+ − 3819
void tst_QScriptEngine::readOnlyPrototypeProperty()
+ − 3820
{
+ − 3821
QSKIP("JSC semantics differ from old back-end and SpiderMonkey", SkipAll);
+ − 3822
QScriptEngine eng;
+ − 3823
QCOMPARE(eng.evaluate("o = {}; o.__proto__ = parseInt; o.length").toInt32(), 2);
+ − 3824
QCOMPARE(eng.evaluate("o.length = 4; o.length").toInt32(), 2);
+ − 3825
QVERIFY(!eng.evaluate("o.hasOwnProperty('length')").toBoolean());
+ − 3826
QCOMPARE(eng.evaluate("o.length *= 2; o.length").toInt32(), 2);
+ − 3827
QCOMPARE(eng.evaluate("o.length /= 2; o.length").toInt32(), 2);
+ − 3828
QCOMPARE(eng.evaluate("o.length %= 2; o.length").toInt32(), 2);
+ − 3829
QCOMPARE(eng.evaluate("o.length += 2; o.length").toInt32(), 2);
+ − 3830
QCOMPARE(eng.evaluate("o.length -= 2; o.length").toInt32(), 2);
+ − 3831
QCOMPARE(eng.evaluate("o.length <<= 2; o.length").toInt32(), 2);
+ − 3832
QCOMPARE(eng.evaluate("o.length >>= 2; o.length").toInt32(), 2);
+ − 3833
QCOMPARE(eng.evaluate("o.length >>>= 2; o.length").toInt32(), 2);
+ − 3834
QCOMPARE(eng.evaluate("o.length &= 0; o.length").toInt32(), 2);
+ − 3835
QCOMPARE(eng.evaluate("o.length ^= 255; o.length").toInt32(), 2);
+ − 3836
QCOMPARE(eng.evaluate("o.length |= 255; o.length").toInt32(), 2);
+ − 3837
+ − 3838
{
+ − 3839
QScriptValue ret = eng.evaluate("o.__defineGetter__('length', function() {})");
+ − 3840
QVERIFY(ret.isError());
+ − 3841
QCOMPARE(ret.toString(), QString::fromLatin1("Error: cannot redefine read-only property"));
+ − 3842
}
+ − 3843
{
+ − 3844
QScriptValue ret = eng.evaluate("o.__defineSetter__('length', function() {})");
+ − 3845
QVERIFY(ret.isError());
+ − 3846
QCOMPARE(ret.toString(), QString::fromLatin1("Error: cannot redefine read-only property"));
+ − 3847
}
+ − 3848
}
+ − 3849
+ − 3850
void tst_QScriptEngine::toObject()
+ − 3851
{
+ − 3852
QScriptEngine eng;
+ − 3853
+ − 3854
QVERIFY(!eng.toObject(eng.undefinedValue()).isValid());
+ − 3855
+ − 3856
QVERIFY(!eng.toObject(eng.nullValue()).isValid());
+ − 3857
+ − 3858
QScriptValue falskt(false);
+ − 3859
{
+ − 3860
QScriptValue tmp = eng.toObject(falskt);
+ − 3861
QVERIFY(tmp.isObject());
+ − 3862
QCOMPARE(tmp.toNumber(), falskt.toNumber());
+ − 3863
}
14
+ − 3864
QVERIFY(falskt.isBool());
0
+ − 3865
+ − 3866
QScriptValue sant(true);
+ − 3867
{
+ − 3868
QScriptValue tmp = eng.toObject(sant);
+ − 3869
QVERIFY(tmp.isObject());
+ − 3870
QCOMPARE(tmp.toNumber(), sant.toNumber());
+ − 3871
}
14
+ − 3872
QVERIFY(sant.isBool());
0
+ − 3873
+ − 3874
QScriptValue number(123.0);
+ − 3875
{
+ − 3876
QScriptValue tmp = eng.toObject(number);
+ − 3877
QVERIFY(tmp.isObject());
+ − 3878
QCOMPARE(tmp.toNumber(), number.toNumber());
+ − 3879
}
14
+ − 3880
QVERIFY(number.isNumber());
0
+ − 3881
+ − 3882
QScriptValue str = QScriptValue(&eng, QString("ciao"));
+ − 3883
{
+ − 3884
QScriptValue tmp = eng.toObject(str);
+ − 3885
QVERIFY(tmp.isObject());
+ − 3886
QCOMPARE(tmp.toString(), str.toString());
+ − 3887
}
14
+ − 3888
QVERIFY(str.isString());
0
+ − 3889
+ − 3890
QScriptValue object = eng.newObject();
+ − 3891
{
+ − 3892
QScriptValue tmp = eng.toObject(object);
+ − 3893
QVERIFY(tmp.isObject());
+ − 3894
QVERIFY(tmp.strictlyEquals(object));
+ − 3895
}
+ − 3896
+ − 3897
QScriptValue qobject = eng.newQObject(this);
+ − 3898
QVERIFY(eng.toObject(qobject).strictlyEquals(qobject));
+ − 3899
+ − 3900
QVERIFY(!eng.toObject(QScriptValue()).isValid());
14
+ − 3901
+ − 3902
// v1 constructors
+ − 3903
+ − 3904
QScriptValue boolValue(&eng, true);
+ − 3905
{
+ − 3906
QScriptValue ret = eng.toObject(boolValue);
+ − 3907
QVERIFY(ret.isObject());
+ − 3908
QCOMPARE(ret.toBool(), boolValue.toBool());
+ − 3909
}
+ − 3910
QVERIFY(boolValue.isBool());
+ − 3911
+ − 3912
QScriptValue numberValue(&eng, 123.0);
+ − 3913
{
+ − 3914
QScriptValue ret = eng.toObject(numberValue);
+ − 3915
QVERIFY(ret.isObject());
+ − 3916
QCOMPARE(ret.toNumber(), numberValue.toNumber());
+ − 3917
}
+ − 3918
QVERIFY(numberValue.isNumber());
+ − 3919
+ − 3920
QScriptValue stringValue(&eng, QString::fromLatin1("foo"));
+ − 3921
{
+ − 3922
QScriptValue ret = eng.toObject(stringValue);
+ − 3923
QVERIFY(ret.isObject());
+ − 3924
QCOMPARE(ret.toString(), stringValue.toString());
+ − 3925
}
+ − 3926
QVERIFY(stringValue.isString());
0
+ − 3927
}
+ − 3928
+ − 3929
void tst_QScriptEngine::reservedWords_data()
+ − 3930
{
+ − 3931
QTest::addColumn<QString>("word");
+ − 3932
QTest::newRow("break") << QString("break");
+ − 3933
QTest::newRow("case") << QString("case");
+ − 3934
QTest::newRow("catch") << QString("catch");
+ − 3935
QTest::newRow("continue") << QString("continue");
+ − 3936
QTest::newRow("default") << QString("default");
+ − 3937
QTest::newRow("delete") << QString("delete");
+ − 3938
QTest::newRow("do") << QString("do");
+ − 3939
QTest::newRow("else") << QString("else");
+ − 3940
QTest::newRow("false") << QString("false");
+ − 3941
QTest::newRow("finally") << QString("finally");
+ − 3942
QTest::newRow("for") << QString("for");
+ − 3943
QTest::newRow("function") << QString("function");
+ − 3944
QTest::newRow("if") << QString("if");
+ − 3945
QTest::newRow("in") << QString("in");
+ − 3946
QTest::newRow("instanceof") << QString("instanceof");
+ − 3947
QTest::newRow("new") << QString("new");
+ − 3948
QTest::newRow("null") << QString("null");
+ − 3949
QTest::newRow("return") << QString("return");
+ − 3950
QTest::newRow("switch") << QString("switch");
+ − 3951
QTest::newRow("this") << QString("this");
+ − 3952
QTest::newRow("throw") << QString("throw");
+ − 3953
QTest::newRow("true") << QString("true");
+ − 3954
QTest::newRow("try") << QString("try");
+ − 3955
QTest::newRow("typeof") << QString("typeof");
+ − 3956
QTest::newRow("var") << QString("var");
+ − 3957
QTest::newRow("void") << QString("void");
+ − 3958
QTest::newRow("while") << QString("while");
+ − 3959
QTest::newRow("with") << QString("with");
+ − 3960
}
+ − 3961
+ − 3962
void tst_QScriptEngine::reservedWords()
+ − 3963
{
+ − 3964
QFETCH(QString, word);
+ − 3965
{
+ − 3966
QScriptEngine eng;
+ − 3967
QScriptValue ret = eng.evaluate(word + " = 123");
+ − 3968
QVERIFY(ret.isError());
+ − 3969
QString str = ret.toString();
+ − 3970
QVERIFY(str.startsWith("SyntaxError") || str.startsWith("ReferenceError"));
+ − 3971
}
+ − 3972
{
+ − 3973
QScriptEngine eng;
+ − 3974
QScriptValue ret = eng.evaluate("var " + word + " = 123");
+ − 3975
QVERIFY(ret.isError());
+ − 3976
QVERIFY(ret.toString().startsWith("SyntaxError"));
+ − 3977
}
+ − 3978
{
+ − 3979
QScriptEngine eng;
+ − 3980
QScriptValue ret = eng.evaluate("o = {}; o." + word + " = 123");
+ − 3981
// in the old back-end and in SpiderMonkey this is allowed, but not in JSC
+ − 3982
QVERIFY(ret.isError());
+ − 3983
QVERIFY(ret.toString().startsWith("SyntaxError"));
+ − 3984
}
+ − 3985
{
+ − 3986
QScriptEngine eng;
+ − 3987
QScriptValue ret = eng.evaluate("o = { " + word + ": 123 }");
+ − 3988
// in the old back-end and in SpiderMonkey this is allowed, but not in JSC
+ − 3989
QVERIFY(ret.isError());
+ − 3990
QVERIFY(ret.toString().startsWith("SyntaxError"));
+ − 3991
}
+ − 3992
{
+ − 3993
// SpiderMonkey allows this, but we don't
+ − 3994
QScriptEngine eng;
+ − 3995
QScriptValue ret = eng.evaluate("function " + word + "() {}");
+ − 3996
QVERIFY(ret.isError());
+ − 3997
QVERIFY(ret.toString().startsWith("SyntaxError"));
+ − 3998
}
+ − 3999
}
+ − 4000
+ − 4001
void tst_QScriptEngine::futureReservedWords_data()
+ − 4002
{
+ − 4003
QTest::addColumn<QString>("word");
+ − 4004
QTest::addColumn<bool>("allowed");
+ − 4005
QTest::newRow("abstract") << QString("abstract") << true;
+ − 4006
QTest::newRow("boolean") << QString("boolean") << true;
+ − 4007
QTest::newRow("byte") << QString("byte") << true;
+ − 4008
QTest::newRow("char") << QString("char") << true;
+ − 4009
QTest::newRow("class") << QString("class") << false;
+ − 4010
QTest::newRow("const") << QString("const") << false;
+ − 4011
QTest::newRow("debugger") << QString("debugger") << false;
+ − 4012
QTest::newRow("double") << QString("double") << true;
+ − 4013
QTest::newRow("enum") << QString("enum") << false;
+ − 4014
QTest::newRow("export") << QString("export") << false;
+ − 4015
QTest::newRow("extends") << QString("extends") << false;
+ − 4016
QTest::newRow("final") << QString("final") << true;
+ − 4017
QTest::newRow("float") << QString("float") << true;
+ − 4018
QTest::newRow("goto") << QString("goto") << true;
+ − 4019
QTest::newRow("implements") << QString("implements") << true;
+ − 4020
QTest::newRow("import") << QString("import") << false;
+ − 4021
QTest::newRow("int") << QString("int") << true;
+ − 4022
QTest::newRow("interface") << QString("interface") << true;
+ − 4023
QTest::newRow("long") << QString("long") << true;
+ − 4024
QTest::newRow("native") << QString("native") << true;
+ − 4025
QTest::newRow("package") << QString("package") << true;
+ − 4026
QTest::newRow("private") << QString("private") << true;
+ − 4027
QTest::newRow("protected") << QString("protected") << true;
+ − 4028
QTest::newRow("public") << QString("public") << true;
+ − 4029
QTest::newRow("short") << QString("short") << true;
+ − 4030
QTest::newRow("static") << QString("static") << true;
+ − 4031
QTest::newRow("super") << QString("super") << false;
+ − 4032
QTest::newRow("synchronized") << QString("synchronized") << true;
+ − 4033
QTest::newRow("throws") << QString("throws") << true;
+ − 4034
QTest::newRow("transient") << QString("transient") << true;
+ − 4035
QTest::newRow("volatile") << QString("volatile") << true;
+ − 4036
}
+ − 4037
+ − 4038
void tst_QScriptEngine::futureReservedWords()
+ − 4039
{
+ − 4040
QFETCH(QString, word);
+ − 4041
QFETCH(bool, allowed);
+ − 4042
{
+ − 4043
QScriptEngine eng;
+ − 4044
QScriptValue ret = eng.evaluate(word + " = 123");
+ − 4045
QCOMPARE(!ret.isError(), allowed);
+ − 4046
}
+ − 4047
{
+ − 4048
QScriptEngine eng;
+ − 4049
QScriptValue ret = eng.evaluate("var " + word + " = 123");
+ − 4050
QCOMPARE(!ret.isError(), allowed);
+ − 4051
}
+ − 4052
{
+ − 4053
// this should probably be allowed (see task 162567)
+ − 4054
QScriptEngine eng;
+ − 4055
QScriptValue ret = eng.evaluate("o = {}; o." + word + " = 123");
+ − 4056
QCOMPARE(ret.isNumber(), allowed);
+ − 4057
QCOMPARE(!ret.isError(), allowed);
+ − 4058
}
+ − 4059
{
+ − 4060
// this should probably be allowed (see task 162567)
+ − 4061
QScriptEngine eng;
+ − 4062
QScriptValue ret = eng.evaluate("o = { " + word + ": 123 }");
+ − 4063
QCOMPARE(!ret.isError(), allowed);
+ − 4064
}
+ − 4065
}
+ − 4066
+ − 4067
void tst_QScriptEngine::throwInsideWithStatement()
+ − 4068
{
+ − 4069
// task 209988
+ − 4070
QScriptEngine eng;
+ − 4071
{
+ − 4072
QScriptValue ret = eng.evaluate(
+ − 4073
"try {"
+ − 4074
" o = { bad : \"bug\" };"
+ − 4075
" with (o) {"
+ − 4076
" throw 123;"
+ − 4077
" }"
+ − 4078
"} catch (e) {"
+ − 4079
" bad;"
+ − 4080
"}");
+ − 4081
QVERIFY(ret.isError());
+ − 4082
QCOMPARE(ret.toString(), QString::fromLatin1("ReferenceError: Can't find variable: bad"));
+ − 4083
}
+ − 4084
{
+ − 4085
QScriptValue ret = eng.evaluate(
+ − 4086
"try {"
+ − 4087
" o = { bad : \"bug\" };"
+ − 4088
" with (o) {"
+ − 4089
" throw 123;"
+ − 4090
" }"
+ − 4091
"} finally {"
+ − 4092
" bad;"
+ − 4093
"}");
+ − 4094
QVERIFY(ret.isError());
+ − 4095
QCOMPARE(ret.toString(), QString::fromLatin1("ReferenceError: Can't find variable: bad"));
+ − 4096
}
+ − 4097
{
+ − 4098
eng.clearExceptions();
+ − 4099
QScriptValue ret = eng.evaluate(
+ − 4100
"o = { bug : \"no bug\" };"
+ − 4101
"with (o) {"
+ − 4102
" try {"
+ − 4103
" throw 123;"
+ − 4104
" } finally {"
+ − 4105
" bug;"
+ − 4106
" }"
+ − 4107
"}");
+ − 4108
QVERIFY(ret.isNumber());
+ − 4109
QCOMPARE(ret.toInt32(), 123);
+ − 4110
QVERIFY(eng.hasUncaughtException());
+ − 4111
}
+ − 4112
{
+ − 4113
eng.clearExceptions();
+ − 4114
QScriptValue ret = eng.evaluate(
+ − 4115
"o = { bug : \"no bug\" };"
+ − 4116
"with (o) {"
+ − 4117
" throw 123;"
+ − 4118
"}");
+ − 4119
QVERIFY(ret.isNumber());
+ − 4120
QScriptValue ret2 = eng.evaluate("bug");
+ − 4121
QVERIFY(ret2.isError());
+ − 4122
QCOMPARE(ret2.toString(), QString::fromLatin1("ReferenceError: Can't find variable: bug"));
+ − 4123
}
+ − 4124
}
+ − 4125
+ − 4126
class TestAgent : public QScriptEngineAgent
+ − 4127
{
+ − 4128
public:
+ − 4129
TestAgent(QScriptEngine *engine) : QScriptEngineAgent(engine) {}
+ − 4130
};
+ − 4131
+ − 4132
void tst_QScriptEngine::getSetAgent()
+ − 4133
{
+ − 4134
// case 1: engine deleted before agent --> agent deleted too
+ − 4135
{
+ − 4136
QScriptEngine *eng = new QScriptEngine;
+ − 4137
QCOMPARE(eng->agent(), (QScriptEngineAgent*)0);
+ − 4138
TestAgent *agent = new TestAgent(eng);
+ − 4139
eng->setAgent(agent);
+ − 4140
QCOMPARE(eng->agent(), (QScriptEngineAgent*)agent);
+ − 4141
eng->setAgent(0); // the engine maintains ownership of the old agent
+ − 4142
QCOMPARE(eng->agent(), (QScriptEngineAgent*)0);
+ − 4143
delete eng;
+ − 4144
}
+ − 4145
// case 2: agent deleted before engine --> engine's agent should become 0
+ − 4146
{
+ − 4147
QScriptEngine *eng = new QScriptEngine;
+ − 4148
TestAgent *agent = new TestAgent(eng);
+ − 4149
eng->setAgent(agent);
+ − 4150
QCOMPARE(eng->agent(), (QScriptEngineAgent*)agent);
+ − 4151
delete agent;
+ − 4152
QCOMPARE(eng->agent(), (QScriptEngineAgent*)0);
+ − 4153
eng->evaluate("(function(){ return 123; })()");
+ − 4154
delete eng;
+ − 4155
}
+ − 4156
{
+ − 4157
QScriptEngine eng;
+ − 4158
QScriptEngine eng2;
+ − 4159
TestAgent *agent = new TestAgent(&eng);
+ − 4160
QTest::ignoreMessage(QtWarningMsg, "QScriptEngine::setAgent(): cannot set agent belonging to different engine");
+ − 4161
eng2.setAgent(agent);
+ − 4162
QCOMPARE(eng2.agent(), (QScriptEngineAgent*)0);
+ − 4163
}
+ − 4164
}
+ − 4165
+ − 4166
void tst_QScriptEngine::reentrancy()
+ − 4167
{
+ − 4168
{
+ − 4169
QScriptEngine eng1;
+ − 4170
QScriptEngine eng2;
+ − 4171
QScriptString s1 = eng1.toStringHandle("foo");
+ − 4172
QScriptString s2 = eng2.toStringHandle("foo");
+ − 4173
QVERIFY(s1 != s2);
+ − 4174
}
+ − 4175
{
+ − 4176
QScriptEngine eng1;
+ − 4177
QScriptEngine eng2;
+ − 4178
eng1.setProcessEventsInterval(123);
+ − 4179
QCOMPARE(eng2.processEventsInterval(), -1);
+ − 4180
eng2.setProcessEventsInterval(456);
+ − 4181
QCOMPARE(eng1.processEventsInterval(), 123);
+ − 4182
}
+ − 4183
{
+ − 4184
QScriptEngine eng1;
+ − 4185
QScriptEngine eng2;
+ − 4186
qScriptRegisterMetaType<Foo>(&eng1, fooToScriptValue, fooFromScriptValue);
+ − 4187
Foo foo;
+ − 4188
foo.x = 12;
+ − 4189
foo.y = 34;
+ − 4190
{
+ − 4191
QScriptValue fooVal = qScriptValueFromValue(&eng1, foo);
+ − 4192
QVERIFY(fooVal.isObject());
+ − 4193
QVERIFY(!fooVal.isVariant());
+ − 4194
QCOMPARE(fooVal.property("x").toInt32(), 12);
+ − 4195
QCOMPARE(fooVal.property("y").toInt32(), 34);
+ − 4196
fooVal.setProperty("x", 56);
+ − 4197
fooVal.setProperty("y", 78);
+ − 4198
+ − 4199
Foo foo2 = qScriptValueToValue<Foo>(fooVal);
+ − 4200
QCOMPARE(foo2.x, 56);
+ − 4201
QCOMPARE(foo2.y, 78);
+ − 4202
}
+ − 4203
{
+ − 4204
QScriptValue fooVal = qScriptValueFromValue(&eng2, foo);
+ − 4205
QVERIFY(fooVal.isVariant());
+ − 4206
+ − 4207
Foo foo2 = qScriptValueToValue<Foo>(fooVal);
+ − 4208
QCOMPARE(foo2.x, 12);
+ − 4209
QCOMPARE(foo2.y, 34);
+ − 4210
}
+ − 4211
QVERIFY(!eng1.defaultPrototype(qMetaTypeId<Foo>()).isValid());
+ − 4212
QVERIFY(!eng2.defaultPrototype(qMetaTypeId<Foo>()).isValid());
+ − 4213
QScriptValue proto1 = eng1.newObject();
+ − 4214
eng1.setDefaultPrototype(qMetaTypeId<Foo>(), proto1);
+ − 4215
QVERIFY(!eng2.defaultPrototype(qMetaTypeId<Foo>()).isValid());
+ − 4216
QScriptValue proto2 = eng2.newObject();
+ − 4217
eng2.setDefaultPrototype(qMetaTypeId<Foo>(), proto2);
+ − 4218
QVERIFY(eng2.defaultPrototype(qMetaTypeId<Foo>()).isValid());
+ − 4219
QVERIFY(eng1.defaultPrototype(qMetaTypeId<Foo>()).strictlyEquals(proto1));
+ − 4220
}
+ − 4221
{
+ − 4222
QScriptEngine eng1;
+ − 4223
QScriptEngine eng2;
+ − 4224
QVERIFY(!eng2.globalObject().property("a").isValid());
+ − 4225
eng1.evaluate("a = 10");
+ − 4226
QVERIFY(eng1.globalObject().property("a").isNumber());
+ − 4227
QVERIFY(!eng2.globalObject().property("a").isValid());
+ − 4228
eng2.evaluate("a = 20");
+ − 4229
QVERIFY(eng2.globalObject().property("a").isNumber());
+ − 4230
QCOMPARE(eng1.globalObject().property("a").toInt32(), 10);
+ − 4231
}
+ − 4232
// weird bug with JSC backend
+ − 4233
{
+ − 4234
QScriptEngine eng;
+ − 4235
QCOMPARE(eng.evaluate("Array()").toString(), QString());
+ − 4236
eng.evaluate("Array.prototype.toString");
+ − 4237
QCOMPARE(eng.evaluate("Array()").toString(), QString());
+ − 4238
}
+ − 4239
{
+ − 4240
QScriptEngine eng;
+ − 4241
QCOMPARE(eng.evaluate("Array()").toString(), QString());
+ − 4242
}
+ − 4243
}
+ − 4244
+ − 4245
void tst_QScriptEngine:: incDecNonObjectProperty()
+ − 4246
{
+ − 4247
QScriptEngine eng;
+ − 4248
{
+ − 4249
QScriptValue ret = eng.evaluate("var a; a.n++");
+ − 4250
QVERIFY(ret.isError());
+ − 4251
QCOMPARE(ret.toString(), QString::fromLatin1("TypeError: Result of expression 'a' [undefined] is not an object."));
+ − 4252
}
+ − 4253
{
+ − 4254
QScriptValue ret = eng.evaluate("var a; a.n--");
+ − 4255
QVERIFY(ret.isError());
+ − 4256
QCOMPARE(ret.toString(), QString::fromLatin1("TypeError: Result of expression 'a' [undefined] is not an object."));
+ − 4257
}
+ − 4258
{
+ − 4259
QScriptValue ret = eng.evaluate("var a = null; a.n++");
+ − 4260
QVERIFY(ret.isError());
+ − 4261
QCOMPARE(ret.toString(), QString::fromLatin1("TypeError: Result of expression 'a' [null] is not an object."));
+ − 4262
}
+ − 4263
{
+ − 4264
QScriptValue ret = eng.evaluate("var a = null; a.n--");
+ − 4265
QVERIFY(ret.isError());
+ − 4266
QCOMPARE(ret.toString(), QString::fromLatin1("TypeError: Result of expression 'a' [null] is not an object."));
+ − 4267
}
+ − 4268
{
+ − 4269
QScriptValue ret = eng.evaluate("var a; ++a.n");
+ − 4270
QVERIFY(ret.isError());
+ − 4271
QCOMPARE(ret.toString(), QString::fromLatin1("TypeError: Result of expression 'a' [null] is not an object."));
+ − 4272
}
+ − 4273
{
+ − 4274
QScriptValue ret = eng.evaluate("var a; --a.n");
+ − 4275
QVERIFY(ret.isError());
+ − 4276
QCOMPARE(ret.toString(), QString::fromLatin1("TypeError: Result of expression 'a' [null] is not an object."));
+ − 4277
}
+ − 4278
{
+ − 4279
QScriptValue ret = eng.evaluate("var a; a.n += 1");
+ − 4280
QVERIFY(ret.isError());
+ − 4281
QCOMPARE(ret.toString(), QString::fromLatin1("TypeError: Result of expression 'a' [null] is not an object."));
+ − 4282
}
+ − 4283
{
+ − 4284
QScriptValue ret = eng.evaluate("var a; a.n -= 1");
+ − 4285
QVERIFY(ret.isError());
+ − 4286
QCOMPARE(ret.toString(), QString::fromLatin1("TypeError: Result of expression 'a' [null] is not an object."));
+ − 4287
}
+ − 4288
{
+ − 4289
QScriptValue ret = eng.evaluate("var a = 'ciao'; a.length++");
+ − 4290
QVERIFY(ret.isNumber());
+ − 4291
QCOMPARE(ret.toInt32(), 4);
+ − 4292
}
+ − 4293
{
+ − 4294
QScriptValue ret = eng.evaluate("var a = 'ciao'; a.length--");
+ − 4295
QVERIFY(ret.isNumber());
+ − 4296
QCOMPARE(ret.toInt32(), 4);
+ − 4297
}
+ − 4298
{
+ − 4299
QScriptValue ret = eng.evaluate("var a = 'ciao'; ++a.length");
+ − 4300
QVERIFY(ret.isNumber());
+ − 4301
QCOMPARE(ret.toInt32(), 5);
+ − 4302
}
+ − 4303
{
+ − 4304
QScriptValue ret = eng.evaluate("var a = 'ciao'; --a.length");
+ − 4305
QVERIFY(ret.isNumber());
+ − 4306
QCOMPARE(ret.toInt32(), 3);
+ − 4307
}
+ − 4308
}
+ − 4309
8
+ − 4310
void tst_QScriptEngine::installTranslatorFunctions_data()
+ − 4311
{
+ − 4312
QTest::addColumn<bool>("useCustomGlobalObject");
+ − 4313
+ − 4314
QTest::newRow("Default global object") << false;
+ − 4315
QTest::newRow("Custom global object") << true;
+ − 4316
}
+ − 4317
0
+ − 4318
void tst_QScriptEngine::installTranslatorFunctions()
+ − 4319
{
8
+ − 4320
QFETCH(bool, useCustomGlobalObject);
+ − 4321
0
+ − 4322
QScriptEngine eng;
8
+ − 4323
QScriptValue globalOrig = eng.globalObject();
+ − 4324
QScriptValue global;
+ − 4325
if (useCustomGlobalObject) {
+ − 4326
global = eng.newObject();
+ − 4327
eng.setGlobalObject(global);
+ − 4328
} else {
+ − 4329
global = globalOrig;
+ − 4330
}
0
+ − 4331
QVERIFY(!global.property("qsTranslate").isValid());
+ − 4332
QVERIFY(!global.property("QT_TRANSLATE_NOOP").isValid());
+ − 4333
QVERIFY(!global.property("qsTr").isValid());
+ − 4334
QVERIFY(!global.property("QT_TR_NOOP").isValid());
8
+ − 4335
QVERIFY(!globalOrig.property("String").property("prototype").property("arg").isValid());
0
+ − 4336
+ − 4337
eng.installTranslatorFunctions();
+ − 4338
QVERIFY(global.property("qsTranslate").isFunction());
+ − 4339
QVERIFY(global.property("QT_TRANSLATE_NOOP").isFunction());
+ − 4340
QVERIFY(global.property("qsTr").isFunction());
+ − 4341
QVERIFY(global.property("QT_TR_NOOP").isFunction());
8
+ − 4342
QVERIFY(globalOrig.property("String").property("prototype").property("arg").isFunction());
+ − 4343
+ − 4344
if (useCustomGlobalObject) {
+ − 4345
QVERIFY(!globalOrig.property("qsTranslate").isValid());
+ − 4346
QVERIFY(!globalOrig.property("QT_TRANSLATE_NOOP").isValid());
+ − 4347
QVERIFY(!globalOrig.property("qsTr").isValid());
+ − 4348
QVERIFY(!globalOrig.property("QT_TR_NOOP").isValid());
+ − 4349
}
0
+ − 4350
+ − 4351
{
+ − 4352
QScriptValue ret = eng.evaluate("qsTr('foo')");
+ − 4353
QVERIFY(ret.isString());
+ − 4354
QCOMPARE(ret.toString(), QString::fromLatin1("foo"));
+ − 4355
}
+ − 4356
{
+ − 4357
QScriptValue ret = eng.evaluate("qsTranslate('foo', 'bar')");
+ − 4358
QVERIFY(ret.isString());
+ − 4359
QCOMPARE(ret.toString(), QString::fromLatin1("bar"));
+ − 4360
}
+ − 4361
{
+ − 4362
QScriptValue ret = eng.evaluate("QT_TR_NOOP('foo')");
+ − 4363
QVERIFY(ret.isString());
+ − 4364
QCOMPARE(ret.toString(), QString::fromLatin1("foo"));
+ − 4365
}
+ − 4366
{
+ − 4367
QScriptValue ret = eng.evaluate("QT_TRANSLATE_NOOP('foo', 'bar')");
+ − 4368
QVERIFY(ret.isString());
+ − 4369
QCOMPARE(ret.toString(), QString::fromLatin1("bar"));
+ − 4370
}
+ − 4371
{
+ − 4372
QScriptValue ret = eng.evaluate("'foo%0'.arg('bar')");
+ − 4373
QVERIFY(ret.isString());
+ − 4374
QCOMPARE(ret.toString(), QString::fromLatin1("foobar"));
+ − 4375
}
+ − 4376
}
+ − 4377
14
+ − 4378
static QScriptValue callQsTr(QScriptContext *ctx, QScriptEngine *eng)
+ − 4379
{
+ − 4380
return eng->globalObject().property("qsTr").call(ctx->thisObject(), ctx->argumentsObject());
+ − 4381
}
+ − 4382
+ − 4383
void tst_QScriptEngine::translateScript()
+ − 4384
{
+ − 4385
QScriptEngine engine;
+ − 4386
+ − 4387
QTranslator translator;
+ − 4388
translator.load(":/translations/translatable_la");
+ − 4389
QCoreApplication::instance()->installTranslator(&translator);
+ − 4390
engine.installTranslatorFunctions();
+ − 4391
+ − 4392
QString fileName = QString::fromLatin1("translatable.js");
+ − 4393
// Top-level
+ − 4394
QCOMPARE(engine.evaluate("qsTr('One')", fileName).toString(), QString::fromLatin1("En"));
+ − 4395
QCOMPARE(engine.evaluate("qsTr('Hello')", fileName).toString(), QString::fromLatin1("Hallo"));
+ − 4396
// From function
+ − 4397
QCOMPARE(engine.evaluate("(function() { return qsTr('One'); })()", fileName).toString(), QString::fromLatin1("En"));
+ − 4398
QCOMPARE(engine.evaluate("(function() { return qsTr('Hello'); })()", fileName).toString(), QString::fromLatin1("Hallo"));
+ − 4399
// From eval
+ − 4400
QCOMPARE(engine.evaluate("eval('qsTr(\\'One\\')')", fileName).toString(), QString::fromLatin1("En"));
+ − 4401
QCOMPARE(engine.evaluate("eval('qsTr(\\'Hello\\')')", fileName).toString(), QString::fromLatin1("Hallo"));
+ − 4402
+ − 4403
QCOMPARE(engine.evaluate("qsTranslate('FooContext', 'Two')", fileName).toString(), QString::fromLatin1("To"));
+ − 4404
QCOMPARE(engine.evaluate("qsTranslate('FooContext', 'Goodbye')", fileName).toString(), QString::fromLatin1("Farvel"));
+ − 4405
// From eval
+ − 4406
QCOMPARE(engine.evaluate("eval('qsTranslate(\\'FooContext\\', \\'Two\\')')", fileName).toString(), QString::fromLatin1("To"));
+ − 4407
QCOMPARE(engine.evaluate("eval('qsTranslate(\\'FooContext\\', \\'Goodbye\\')')", fileName).toString(), QString::fromLatin1("Farvel"));
+ − 4408
+ − 4409
QCOMPARE(engine.evaluate("qsTranslate('FooContext', 'Goodbye', '', 'UnicodeUTF8')", fileName).toString(), QString::fromLatin1("Farvel"));
+ − 4410
+ − 4411
QCOMPARE(engine.evaluate("qsTr('One', 'not the same one')", fileName).toString(), QString::fromLatin1("Enda en"));
+ − 4412
+ − 4413
QVERIFY(engine.evaluate("QT_TR_NOOP()").isUndefined());
+ − 4414
QCOMPARE(engine.evaluate("QT_TR_NOOP('One')").toString(), QString::fromLatin1("One"));
+ − 4415
+ − 4416
QVERIFY(engine.evaluate("QT_TRANSLATE_NOOP()").isUndefined());
+ − 4417
QVERIFY(engine.evaluate("QT_TRANSLATE_NOOP('FooContext')").isUndefined());
+ − 4418
QCOMPARE(engine.evaluate("QT_TRANSLATE_NOOP('FooContext', 'Two')").toString(), QString::fromLatin1("Two"));
+ − 4419
+ − 4420
// Don't exist in translation
+ − 4421
QCOMPARE(engine.evaluate("qsTr('Three')", fileName).toString(), QString::fromLatin1("Three"));
+ − 4422
QCOMPARE(engine.evaluate("qsTranslate('FooContext', 'So long')", fileName).toString(), QString::fromLatin1("So long"));
+ − 4423
QCOMPARE(engine.evaluate("qsTranslate('BarContext', 'Goodbye')", fileName).toString(), QString::fromLatin1("Goodbye"));
+ − 4424
+ − 4425
// From C++
+ − 4426
// There is no context, but it shouldn't crash
+ − 4427
QCOMPARE(engine.globalObject().property("qsTr").call(
+ − 4428
QScriptValue(), QScriptValueList() << "One").toString(), QString::fromLatin1("One"));
+ − 4429
+ − 4430
// Translate strings from the second script (translatable2.js)
+ − 4431
+ − 4432
QString fileName2 = QString::fromLatin1("translatable2.js");
+ − 4433
+ − 4434
QCOMPARE(engine.evaluate("qsTr('Three')", fileName2).toString(), QString::fromLatin1("Tre"));
+ − 4435
QCOMPARE(engine.evaluate("qsTr('Happy birthday!')", fileName2).toString(), QString::fromLatin1("Gratulerer med dagen!"));
+ − 4436
+ − 4437
// Not translated because translation is only in translatable.js
+ − 4438
QCOMPARE(engine.evaluate("qsTr('One')", fileName2).toString(), QString::fromLatin1("One"));
+ − 4439
QCOMPARE(engine.evaluate("(function() { return qsTr('One'); })()", fileName2).toString(), QString::fromLatin1("One"));
+ − 4440
+ − 4441
// For qsTranslate() the filename shouldn't matter
+ − 4442
QCOMPARE(engine.evaluate("qsTranslate('FooContext', 'Two')", fileName2).toString(), QString::fromLatin1("To"));
+ − 4443
QCOMPARE(engine.evaluate("qsTranslate('BarContext', 'Congratulations!')", fileName).toString(), QString::fromLatin1("Gratulerer!"));
+ − 4444
+ − 4445
// qsTr() should use the innermost filename as context
+ − 4446
engine.evaluate("function foo(s) { return bar(s); }", fileName);
+ − 4447
engine.evaluate("function bar(s) { return qsTr(s); }", fileName2);
+ − 4448
QCOMPARE(engine.evaluate("bar('Three')", fileName2).toString(), QString::fromLatin1("Tre"));
+ − 4449
QCOMPARE(engine.evaluate("bar('Three')", fileName).toString(), QString::fromLatin1("Tre"));
+ − 4450
QCOMPARE(engine.evaluate("bar('One')", fileName2).toString(), QString::fromLatin1("One"));
+ − 4451
+ − 4452
engine.evaluate("function foo(s) { return bar(s); }", fileName2);
+ − 4453
engine.evaluate("function bar(s) { return qsTr(s); }", fileName);
+ − 4454
QCOMPARE(engine.evaluate("bar('Three')", fileName2).toString(), QString::fromLatin1("Three"));
+ − 4455
QCOMPARE(engine.evaluate("bar('One')", fileName).toString(), QString::fromLatin1("En"));
+ − 4456
QCOMPARE(engine.evaluate("bar('One')", fileName2).toString(), QString::fromLatin1("En"));
+ − 4457
+ − 4458
// Calling qsTr() from a native function
+ − 4459
engine.globalObject().setProperty("qsTrProxy", engine.newFunction(callQsTr));
+ − 4460
QCOMPARE(engine.evaluate("qsTrProxy('One')", fileName).toString(), QString::fromLatin1("En"));
+ − 4461
QCOMPARE(engine.evaluate("qsTrProxy('One')", fileName2).toString(), QString::fromLatin1("One"));
+ − 4462
QCOMPARE(engine.evaluate("qsTrProxy('Three')", fileName).toString(), QString::fromLatin1("Three"));
+ − 4463
QCOMPARE(engine.evaluate("qsTrProxy('Three')", fileName2).toString(), QString::fromLatin1("Tre"));
+ − 4464
+ − 4465
QCoreApplication::instance()->removeTranslator(&translator);
+ − 4466
}
+ − 4467
+ − 4468
void tst_QScriptEngine::translateWithInvalidArgs_data()
+ − 4469
{
+ − 4470
QTest::addColumn<QString>("expression");
+ − 4471
QTest::addColumn<QString>("expectedError");
+ − 4472
+ − 4473
QTest::newRow("qsTr()") << "qsTr()" << "Error: qsTr() requires at least one argument";
+ − 4474
QTest::newRow("qsTr(123)") << "qsTr(123)" << "Error: qsTr(): first argument (text) must be a string";
+ − 4475
QTest::newRow("qsTr('foo', 123)") << "qsTr('foo', 123)" << "Error: qsTr(): second argument (comment) must be a string";
+ − 4476
QTest::newRow("qsTr('foo', 'bar', 'baz')") << "qsTr('foo', 'bar', 'baz')" << "Error: qsTr(): third argument (n) must be a number";
+ − 4477
QTest::newRow("qsTr('foo', 'bar', true)") << "qsTr('foo', 'bar', true)" << "Error: qsTr(): third argument (n) must be a number";
+ − 4478
+ − 4479
QTest::newRow("qsTranslate()") << "qsTranslate()" << "Error: qsTranslate() requires at least two arguments";
+ − 4480
QTest::newRow("qsTranslate('foo')") << "qsTranslate('foo')" << "Error: qsTranslate() requires at least two arguments";
+ − 4481
QTest::newRow("qsTranslate('foo', 123)") << "qsTranslate('foo', 123)" << "Error: qsTranslate(): second argument (text) must be a string";
+ − 4482
QTest::newRow("qsTranslate('foo', 'bar', 123)") << "qsTranslate('foo', 'bar', 123)" << "Error: qsTranslate(): third argument (comment) must be a string";
+ − 4483
QTest::newRow("qsTranslate('foo', 'bar', 'baz', 123)") << "qsTranslate('foo', 'bar', 'baz', 123)" << "Error: qsTranslate(): fourth argument (encoding) must be a string";
+ − 4484
QTest::newRow("qsTranslate('foo', 'bar', 'baz', 'zab', 'rab')") << "qsTranslate('foo', 'bar', 'baz', 'zab', 'rab')" << "Error: qsTranslate(): fifth argument (n) must be a number";
+ − 4485
QTest::newRow("qsTranslate('foo', 'bar', 'baz', 'zab', 123)") << "qsTranslate('foo', 'bar', 'baz', 'zab', 123)" << "Error: qsTranslate(): invalid encoding 'zab'";
+ − 4486
}
+ − 4487
+ − 4488
void tst_QScriptEngine::translateWithInvalidArgs()
+ − 4489
{
+ − 4490
QFETCH(QString, expression);
+ − 4491
QFETCH(QString, expectedError);
+ − 4492
QScriptEngine engine;
+ − 4493
engine.installTranslatorFunctions();
+ − 4494
QScriptValue result = engine.evaluate(expression);
+ − 4495
QVERIFY(result.isError());
+ − 4496
QCOMPARE(result.toString(), expectedError);
+ − 4497
}
+ − 4498
+ − 4499
void tst_QScriptEngine::translationContext_data()
+ − 4500
{
+ − 4501
QTest::addColumn<QString>("path");
+ − 4502
QTest::addColumn<QString>("text");
+ − 4503
QTest::addColumn<QString>("expectedTranslation");
+ − 4504
+ − 4505
QTest::newRow("translatable.js") << "translatable.js" << "One" << "En";
+ − 4506
QTest::newRow("/translatable.js") << "/translatable.js" << "One" << "En";
+ − 4507
QTest::newRow("/foo/translatable.js") << "/foo/translatable.js" << "One" << "En";
+ − 4508
QTest::newRow("/foo/bar/translatable.js") << "/foo/bar/translatable.js" << "One" << "En";
+ − 4509
QTest::newRow("./translatable.js") << "./translatable.js" << "One" << "En";
+ − 4510
QTest::newRow("../translatable.js") << "../translatable.js" << "One" << "En";
+ − 4511
QTest::newRow("foo/translatable.js") << "foo/translatable.js" << "One" << "En";
+ − 4512
QTest::newRow("file:///home/qt/translatable.js") << "file:///home/qt/translatable.js" << "One" << "En";
+ − 4513
QTest::newRow(":/resources/translatable.js") << ":/resources/translatable.js" << "One" << "En";
+ − 4514
QTest::newRow("/translatable.js.foo") << "/translatable.js.foo" << "One" << "En";
+ − 4515
QTest::newRow("/translatable.txt") << "/translatable.txt" << "One" << "En";
+ − 4516
QTest::newRow("translatable") << "translatable" << "One" << "En";
+ − 4517
QTest::newRow("foo/translatable") << "foo/translatable" << "One" << "En";
+ − 4518
+ − 4519
QTest::newRow("native separators")
+ − 4520
<< (QDir::toNativeSeparators(QDir::currentPath()) + QDir::separator() + "translatable.js")
+ − 4521
<< "One" << "En";
+ − 4522
+ − 4523
QTest::newRow("translatable.js/") << "translatable.js/" << "One" << "One";
+ − 4524
QTest::newRow("nosuchscript.js") << "" << "One" << "One";
+ − 4525
QTest::newRow("(empty)") << "" << "One" << "One";
+ − 4526
}
+ − 4527
+ − 4528
void tst_QScriptEngine::translationContext()
+ − 4529
{
+ − 4530
QTranslator translator;
+ − 4531
translator.load(":/translations/translatable_la");
+ − 4532
QCoreApplication::instance()->installTranslator(&translator);
+ − 4533
+ − 4534
QScriptEngine engine;
+ − 4535
engine.installTranslatorFunctions();
+ − 4536
+ − 4537
QFETCH(QString, path);
+ − 4538
QFETCH(QString, text);
+ − 4539
QFETCH(QString, expectedTranslation);
+ − 4540
QScriptValue ret = engine.evaluate(QString::fromLatin1("qsTr('%0')").arg(text), path);
+ − 4541
QVERIFY(ret.isString());
+ − 4542
QCOMPARE(ret.toString(), expectedTranslation);
+ − 4543
+ − 4544
QCoreApplication::instance()->removeTranslator(&translator);
+ − 4545
}
+ − 4546
0
+ − 4547
void tst_QScriptEngine::functionScopes()
+ − 4548
{
+ − 4549
QScriptEngine eng;
+ − 4550
{
+ − 4551
// top-level functions have only the global object in their scope
+ − 4552
QScriptValue fun = eng.evaluate("(function() {})");
+ − 4553
QVERIFY(fun.isFunction());
+ − 4554
QEXPECT_FAIL("", "Function scope proxying is not implemented", Abort);
+ − 4555
QVERIFY(fun.scope().isObject());
+ − 4556
QVERIFY(fun.scope().strictlyEquals(eng.globalObject()));
+ − 4557
QVERIFY(!eng.globalObject().scope().isValid());
+ − 4558
}
+ − 4559
{
+ − 4560
QScriptValue fun = eng.globalObject().property("Object");
+ − 4561
QVERIFY(fun.isFunction());
+ − 4562
// native built-in functions don't have scope
+ − 4563
QVERIFY(!fun.scope().isValid());
+ − 4564
}
+ − 4565
{
+ − 4566
// closure
+ − 4567
QScriptValue fun = eng.evaluate("(function(arg) { var foo = arg; return function() { return foo; }; })(123)");
+ − 4568
QVERIFY(fun.isFunction());
+ − 4569
{
+ − 4570
QScriptValue ret = fun.call();
+ − 4571
QVERIFY(ret.isNumber());
+ − 4572
QCOMPARE(ret.toInt32(), 123);
+ − 4573
}
+ − 4574
QScriptValue scope = fun.scope();
+ − 4575
QVERIFY(scope.isObject());
+ − 4576
{
+ − 4577
QScriptValue ret = scope.property("foo");
+ − 4578
QVERIFY(ret.isNumber());
+ − 4579
QCOMPARE(ret.toInt32(), 123);
+ − 4580
QCOMPARE(scope.propertyFlags("foo"), QScriptValue::Undeletable);
+ − 4581
}
+ − 4582
{
+ − 4583
QScriptValue ret = scope.property("arg");
+ − 4584
QVERIFY(ret.isNumber());
+ − 4585
QCOMPARE(ret.toInt32(), 123);
+ − 4586
QCOMPARE(scope.propertyFlags("arg"), QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
+ − 4587
}
+ − 4588
+ − 4589
scope.setProperty("foo", 456);
+ − 4590
{
+ − 4591
QScriptValue ret = fun.call();
+ − 4592
QVERIFY(ret.isNumber());
+ − 4593
QCOMPARE(ret.toInt32(), 456);
+ − 4594
}
+ − 4595
+ − 4596
scope = scope.scope();
+ − 4597
QVERIFY(scope.isObject());
+ − 4598
QVERIFY(scope.strictlyEquals(eng.globalObject()));
+ − 4599
}
+ − 4600
}
+ − 4601
+ − 4602
static QScriptValue counter_inner(QScriptContext *ctx, QScriptEngine *)
+ − 4603
{
+ − 4604
QScriptValue outerAct = ctx->callee().scope();
+ − 4605
double count = outerAct.property("count").toNumber();
+ − 4606
outerAct.setProperty("count", count+1);
+ − 4607
return count;
+ − 4608
}
+ − 4609
+ − 4610
static QScriptValue counter(QScriptContext *ctx, QScriptEngine *eng)
+ − 4611
{
+ − 4612
QScriptValue act = ctx->activationObject();
+ − 4613
act.setProperty("count", ctx->argument(0).toInt32());
+ − 4614
QScriptValue result = eng->newFunction(counter_inner);
+ − 4615
result.setScope(act);
+ − 4616
return result;
+ − 4617
}
+ − 4618
+ − 4619
static QScriptValue counter_hybrid(QScriptContext *ctx, QScriptEngine *eng)
+ − 4620
{
+ − 4621
QScriptValue act = ctx->activationObject();
+ − 4622
act.setProperty("count", ctx->argument(0).toInt32());
+ − 4623
return eng->evaluate("(function() { return count++; })");
+ − 4624
}
+ − 4625
+ − 4626
void tst_QScriptEngine::nativeFunctionScopes()
+ − 4627
{
+ − 4628
QScriptEngine eng;
+ − 4629
{
+ − 4630
QScriptValue fun = eng.newFunction(counter);
+ − 4631
QScriptValue cnt = fun.call(QScriptValue(), QScriptValueList() << 123);
+ − 4632
QVERIFY(cnt.isFunction());
+ − 4633
{
+ − 4634
QScriptValue ret = cnt.call();
+ − 4635
QVERIFY(ret.isNumber());
+ − 4636
QCOMPARE(ret.toInt32(), 123);
+ − 4637
}
+ − 4638
}
+ − 4639
{
+ − 4640
QScriptValue fun = eng.newFunction(counter_hybrid);
+ − 4641
QScriptValue cnt = fun.call(QScriptValue(), QScriptValueList() << 123);
+ − 4642
QVERIFY(cnt.isFunction());
+ − 4643
{
+ − 4644
QScriptValue ret = cnt.call();
+ − 4645
QVERIFY(ret.isNumber());
+ − 4646
QCOMPARE(ret.toInt32(), 123);
+ − 4647
}
+ − 4648
}
+ − 4649
+ − 4650
//from http://doc.trolltech.com/latest/qtscript.html#nested-functions-and-the-scope-chain
+ − 4651
{
+ − 4652
QScriptEngine eng;
+ − 4653
eng.evaluate("function counter() { var count = 0; return function() { return count++; } }\n"
+ − 4654
"var c1 = counter(); var c2 = counter(); ");
+ − 4655
QCOMPARE(eng.evaluate("c1()").toString(), QString::fromLatin1("0"));
+ − 4656
QCOMPARE(eng.evaluate("c1()").toString(), QString::fromLatin1("1"));
+ − 4657
QCOMPARE(eng.evaluate("c2()").toString(), QString::fromLatin1("0"));
+ − 4658
QCOMPARE(eng.evaluate("c2()").toString(), QString::fromLatin1("1"));
+ − 4659
QVERIFY(!eng.hasUncaughtException());
+ − 4660
}
+ − 4661
{
+ − 4662
QScriptEngine eng;
+ − 4663
eng.globalObject().setProperty("counter", eng.newFunction(counter));
+ − 4664
eng.evaluate("var c1 = counter(); var c2 = counter(); ");
+ − 4665
QCOMPARE(eng.evaluate("c1()").toString(), QString::fromLatin1("0"));
+ − 4666
QCOMPARE(eng.evaluate("c1()").toString(), QString::fromLatin1("1"));
+ − 4667
QCOMPARE(eng.evaluate("c2()").toString(), QString::fromLatin1("0"));
+ − 4668
QCOMPARE(eng.evaluate("c2()").toString(), QString::fromLatin1("1"));
+ − 4669
QVERIFY(!eng.hasUncaughtException());
+ − 4670
}
+ − 4671
{
+ − 4672
QScriptEngine eng;
+ − 4673
eng.globalObject().setProperty("counter", eng.newFunction(counter_hybrid));
+ − 4674
eng.evaluate("var c1 = counter(); var c2 = counter(); ");
+ − 4675
QCOMPARE(eng.evaluate("c1()").toString(), QString::fromLatin1("0"));
+ − 4676
QCOMPARE(eng.evaluate("c1()").toString(), QString::fromLatin1("1"));
+ − 4677
QCOMPARE(eng.evaluate("c2()").toString(), QString::fromLatin1("0"));
+ − 4678
QCOMPARE(eng.evaluate("c2()").toString(), QString::fromLatin1("1"));
+ − 4679
QVERIFY(!eng.hasUncaughtException());
+ − 4680
}
+ − 4681
}
+ − 4682
3
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4683
static QScriptValue createProgram(QScriptContext *ctx, QScriptEngine *eng)
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4684
{
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4685
QString code = ctx->argument(0).toString();
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4686
QScriptProgram result(code);
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4687
return qScriptValueFromValue(eng, result);
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4688
}
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4689
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4690
void tst_QScriptEngine::evaluateProgram()
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4691
{
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4692
QScriptEngine eng;
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4693
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4694
{
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4695
QString code("1 + 2");
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4696
QString fileName("hello.js");
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4697
int lineNumber(123);
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4698
QScriptProgram program(code, fileName, lineNumber);
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4699
QVERIFY(!program.isNull());
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4700
QCOMPARE(program.sourceCode(), code);
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4701
QCOMPARE(program.fileName(), fileName);
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4702
QCOMPARE(program.firstLineNumber(), lineNumber);
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4703
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4704
QScriptValue expected = eng.evaluate(code);
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4705
for (int x = 0; x < 10; ++x) {
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4706
QScriptValue ret = eng.evaluate(program);
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4707
QVERIFY(ret.equals(expected));
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4708
}
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4709
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4710
// operator=
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4711
QScriptProgram sameProgram = program;
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4712
QVERIFY(sameProgram == program);
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4713
QVERIFY(eng.evaluate(sameProgram).equals(expected));
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4714
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4715
// copy constructor
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4716
QScriptProgram sameProgram2(program);
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4717
QVERIFY(sameProgram2 == program);
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4718
QVERIFY(eng.evaluate(sameProgram2).equals(expected));
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4719
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4720
QScriptProgram differentProgram("2 + 3");
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4721
QVERIFY(differentProgram != program);
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4722
QVERIFY(!eng.evaluate(differentProgram).equals(expected));
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4723
}
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4724
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4725
// Program that accesses variable in the scope
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4726
{
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4727
QScriptProgram program("a");
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4728
QVERIFY(!program.isNull());
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4729
{
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4730
QScriptValue ret = eng.evaluate(program);
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4731
QVERIFY(ret.isError());
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4732
QCOMPARE(ret.toString(), QString::fromLatin1("ReferenceError: Can't find variable: a"));
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4733
}
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4734
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4735
QScriptValue obj = eng.newObject();
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4736
obj.setProperty("a", 123);
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4737
QScriptContext *ctx = eng.currentContext();
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4738
ctx->pushScope(obj);
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4739
{
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4740
QScriptValue ret = eng.evaluate(program);
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4741
QVERIFY(!ret.isError());
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4742
QVERIFY(ret.equals(obj.property("a")));
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4743
}
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4744
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4745
obj.setProperty("a", QScriptValue());
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4746
{
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4747
QScriptValue ret = eng.evaluate(program);
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4748
QVERIFY(ret.isError());
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4749
}
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4750
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4751
QScriptValue obj2 = eng.newObject();
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4752
obj2.setProperty("a", 456);
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4753
ctx->pushScope(obj2);
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4754
{
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4755
QScriptValue ret = eng.evaluate(program);
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4756
QVERIFY(!ret.isError());
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4757
QVERIFY(ret.equals(obj2.property("a")));
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4758
}
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4759
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4760
ctx->popScope();
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4761
}
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4762
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4763
// Program that creates closure
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4764
{
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4765
QScriptProgram program("(function() { var count = 0; return function() { return count++; }; })");
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4766
QVERIFY(!program.isNull());
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4767
QScriptValue createCounter = eng.evaluate(program);
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4768
QVERIFY(createCounter.isFunction());
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4769
QScriptValue counter = createCounter.call();
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4770
QVERIFY(counter.isFunction());
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4771
{
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4772
QScriptValue ret = counter.call();
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4773
QVERIFY(ret.isNumber());
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4774
}
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4775
QScriptValue counter2 = createCounter.call();
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4776
QVERIFY(counter2.isFunction());
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4777
QVERIFY(!counter2.equals(counter));
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4778
{
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4779
QScriptValue ret = counter2.call();
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4780
QVERIFY(ret.isNumber());
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4781
}
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4782
}
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4783
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4784
// Program created in a function call, then executed later
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4785
{
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4786
QScriptValue fun = eng.newFunction(createProgram);
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4787
QScriptProgram program = qscriptvalue_cast<QScriptProgram>(
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4788
fun.call(QScriptValue(), QScriptValueList() << "a + 1"));
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4789
QVERIFY(!program.isNull());
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4790
eng.globalObject().setProperty("a", QScriptValue());
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4791
{
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4792
QScriptValue ret = eng.evaluate(program);
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4793
QVERIFY(ret.isError());
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4794
QCOMPARE(ret.toString(), QString::fromLatin1("ReferenceError: Can't find variable: a"));
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4795
}
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4796
eng.globalObject().setProperty("a", 122);
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4797
{
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4798
QScriptValue ret = eng.evaluate(program);
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4799
QVERIFY(!ret.isError());
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4800
QVERIFY(ret.isNumber());
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4801
QCOMPARE(ret.toInt32(), 123);
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4802
}
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4803
}
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4804
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4805
// Same program run in different engines
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4806
{
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4807
QString code("1 + 2");
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4808
QScriptProgram program(code);
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4809
QVERIFY(!program.isNull());
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4810
double expected = eng.evaluate(program).toNumber();
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4811
for (int x = 0; x < 2; ++x) {
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4812
QScriptEngine eng2;
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4813
for (int y = 0; y < 2; ++y) {
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4814
double ret = eng2.evaluate(program).toNumber();
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4815
QCOMPARE(ret, expected);
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4816
}
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4817
}
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4818
}
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4819
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4820
// No program
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4821
{
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4822
QScriptProgram program;
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4823
QVERIFY(program.isNull());
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4824
QScriptValue ret = eng.evaluate(program);
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4825
QVERIFY(!ret.isValid());
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4826
}
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4827
}
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4828
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4829
void tst_QScriptEngine::collectGarbageAfterConnect()
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4830
{
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4831
// QTBUG-6366
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4832
QScriptEngine engine;
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4833
QPointer<QWidget> widget = new QWidget;
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4834
engine.globalObject().setProperty(
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4835
"widget", engine.newQObject(widget, QScriptEngine::ScriptOwnership));
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4836
QVERIFY(engine.evaluate("widget.customContextMenuRequested.connect(\n"
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4837
" function() { print('hello'); }\n"
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4838
");")
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4839
.isUndefined());
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4840
QVERIFY(widget != 0);
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4841
engine.evaluate("widget = null;");
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4842
collectGarbage_helper(engine);
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4843
QVERIFY(widget == 0);
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4844
}
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4845
0
+ − 4846
static QRegExp minimal(QRegExp r) { r.setMinimal(true); return r; }
+ − 4847
+ − 4848
void tst_QScriptEngine::qRegExpInport_data()
+ − 4849
{
+ − 4850
QTest::addColumn<QRegExp>("rx");
+ − 4851
QTest::addColumn<QString>("string");
+ − 4852
QTest::addColumn<QString>("matched");
+ − 4853
+ − 4854
QTest::newRow("normal") << QRegExp("(test|foo)") << "test _ foo _ test _ Foo";
+ − 4855
QTest::newRow("normal2") << QRegExp("(Test|Foo)") << "test _ foo _ test _ Foo";
+ − 4856
QTest::newRow("case insensitive)") << QRegExp("(test|foo)", Qt::CaseInsensitive) << "test _ foo _ test _ Foo";
+ − 4857
QTest::newRow("case insensitive2)") << QRegExp("(Test|Foo)", Qt::CaseInsensitive) << "test _ foo _ test _ Foo";
+ − 4858
QTest::newRow("b(a*)(b*)") << QRegExp("b(a*)(b*)", Qt::CaseInsensitive) << "aaabbBbaAabaAaababaaabbaaab";
+ − 4859
QTest::newRow("greedy") << QRegExp("a*(a*)", Qt::CaseInsensitive, QRegExp::RegExp2) << "aaaabaaba";
+ − 4860
// this one will fail because we do not support the QRegExp::RegExp in JSC
+ − 4861
//QTest::newRow("not_greedy") << QRegExp("a*(a*)", Qt::CaseInsensitive, QRegExp::RegExp) << "aaaabaaba";
+ − 4862
QTest::newRow("willcard") << QRegExp("*.txt", Qt::CaseSensitive, QRegExp::Wildcard) << "file.txt";
+ − 4863
QTest::newRow("willcard 2") << QRegExp("a?b.txt", Qt::CaseSensitive, QRegExp::Wildcard) << "ab.txt abb.rtc acb.txt";
+ − 4864
QTest::newRow("slash") << QRegExp("g/.*/s", Qt::CaseInsensitive, QRegExp::RegExp2) << "string/string/string";
+ − 4865
QTest::newRow("slash2") << QRegExp("g / .* / s", Qt::CaseInsensitive, QRegExp::RegExp2) << "string / string / string";
+ − 4866
QTest::newRow("fixed") << QRegExp("a*aa.a(ba)*a\\ba", Qt::CaseInsensitive, QRegExp::FixedString) << "aa*aa.a(ba)*a\\ba";
+ − 4867
QTest::newRow("fixed insensitive") << QRegExp("A*A", Qt::CaseInsensitive, QRegExp::FixedString) << "a*A A*a A*A a*a";
+ − 4868
QTest::newRow("fixed sensitive") << QRegExp("A*A", Qt::CaseSensitive, QRegExp::FixedString) << "a*A A*a A*A a*a";
+ − 4869
QTest::newRow("html") << QRegExp("<b>(.*)</b>", Qt::CaseSensitive, QRegExp::RegExp2) << "<b>bold</b><i>italic</i><b>bold</b>";
+ − 4870
QTest::newRow("html minimal") << minimal(QRegExp("<b>(.*)</b>", Qt::CaseSensitive, QRegExp::RegExp2)) << "<b>bold</b><i>italic</i><b>bold</b>";
+ − 4871
QTest::newRow("aaa") << QRegExp("a{2,5}") << "aAaAaaaaaAa";
+ − 4872
QTest::newRow("aaa minimal") << minimal(QRegExp("a{2,5}")) << "aAaAaaaaaAa";
+ − 4873
QTest::newRow("minimal") << minimal(QRegExp(".*\\} [*8]")) << "}?} ?} *";
+ − 4874
}
+ − 4875
+ − 4876
void tst_QScriptEngine::qRegExpInport()
+ − 4877
{
+ − 4878
QFETCH(QRegExp, rx);
+ − 4879
QFETCH(QString, string);
+ − 4880
+ − 4881
QScriptEngine eng;
+ − 4882
QScriptValue rexp;
+ − 4883
rexp = eng.newRegExp(rx);
+ − 4884
+ − 4885
QCOMPARE(rexp.isValid(), true);
+ − 4886
QCOMPARE(rexp.isRegExp(), true);
+ − 4887
QVERIFY(rexp.isFunction());
+ − 4888
+ − 4889
QScriptValue func = eng.evaluate("(function(string, regexp) { return string.match(regexp); })");
+ − 4890
QScriptValue result = func.call(QScriptValue(), QScriptValueList() << string << rexp);
+ − 4891
+ − 4892
rx.indexIn(string);
3
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
diff
changeset
+ − 4893
for (int i = 0; i <= rx.captureCount(); i++) {
0
+ − 4894
QCOMPARE(result.property(i).toString(), rx.cap(i));
+ − 4895
}
+ − 4896
}
+ − 4897
+ − 4898
QTEST_MAIN(tst_QScriptEngine)
+ − 4899
#include "tst_qscriptengine.moc"