void tst_QScriptContext::thisObject() { QScriptEngine eng; QScriptValue fun = eng.newFunction(get_thisObject); eng.globalObject().setProperty("get_thisObject", fun); { QScriptValue result = eng.evaluate("get_thisObject()"); QCOMPARE(result.isObject(), true); QCOMPARE(result.toString(), QString("[object global]")); } { QScriptValue result = eng.evaluate("get_thisObject.apply(new Number(123))"); QCOMPARE(result.isObject(), true); QCOMPARE(result.toNumber(), 123.0); } { QScriptValue obj = eng.newObject(); eng.currentContext()->setThisObject(obj); QVERIFY(eng.currentContext()->thisObject().equals(obj)); eng.currentContext()->setThisObject(QScriptValue()); QVERIFY(eng.currentContext()->thisObject().equals(obj)); QScriptEngine eng2; QScriptValue obj2 = eng2.newObject(); QTest::ignoreMessage(QtWarningMsg, "QScriptContext::setThisObject() failed: cannot set an object created in a different engine"); eng.currentContext()->setThisObject(obj2); } }
void tst_QScriptContext::returnValue() { QSKIP("Internal function not implemented in JSC-based back-end", SkipAll); QScriptEngine eng; eng.evaluate("123"); QCOMPARE(eng.currentContext()->returnValue().toNumber(), 123.0); eng.evaluate("\"ciao\""); QCOMPARE(eng.currentContext()->returnValue().toString(), QString("ciao")); }
QScriptValue ScriptFunctionWrapper::callWith(const QScriptValue &val) { //qDebug() << "Call called" << d->name; QScriptEngine *eng = val.engine(); if (!eng) { qDebug() << "We cannot access the script-engine, fail!"; return QScriptValue(); } QScriptContext *ctx = eng->currentContext(); return d->object.property(d->name).call(QScriptValue(), ctx->argumentsObject()); }
bool XTreeView::throwScriptException(const QString &message) { QObject *ancestor = this; QScriptEngine *engine = 0; for ( ; ancestor; ancestor = ancestor->parent()) { engine = ancestor->findChild<QScriptEngine*>(); if (engine) break; } if (engine) { QScriptContext *ctx = engine->currentContext(); ctx->throwError(message); return true; } return false; }
void tst_QScriptContext::scopeChain() { QScriptEngine eng; { QScriptValueList ret = eng.currentContext()->scopeChain(); QCOMPARE(ret.size(), 1); QVERIFY(ret.at(0).strictlyEquals(eng.globalObject())); } { eng.globalObject().setProperty("getScopeChain", eng.newFunction(getScopeChain)); QScriptValueList ret = qscriptvalue_cast<QScriptValueList>(eng.evaluate("getScopeChain()")); QCOMPARE(ret.size(), 1); QVERIFY(ret.at(0).strictlyEquals(eng.globalObject())); } { eng.evaluate("function foo() { function bar() { return getScopeChain(); } return bar() }"); QScriptValueList ret = qscriptvalue_cast<QScriptValueList>(eng.evaluate("foo()")); QEXPECT_FAIL("", "Number of items in returned scope chain is incorrect", Abort); QCOMPARE(ret.size(), 3); QVERIFY(ret.at(2).strictlyEquals(eng.globalObject())); QCOMPARE(ret.at(1).toString(), QString::fromLatin1("activation")); QVERIFY(ret.at(1).property("arguments").isObject()); QCOMPARE(ret.at(0).toString(), QString::fromLatin1("activation")); QVERIFY(ret.at(0).property("arguments").isObject()); } { QScriptValueList ret = qscriptvalue_cast<QScriptValueList>(eng.evaluate("o = { x: 123 }; with(o) getScopeChain();")); QCOMPARE(ret.size(), 2); QVERIFY(ret.at(1).strictlyEquals(eng.globalObject())); QVERIFY(ret.at(0).isObject()); QCOMPARE(ret.at(0).property("x").toInt32(), 123); } { QScriptValueList ret = qscriptvalue_cast<QScriptValueList>( eng.evaluate("o1 = { x: 123}; o2 = { y: 456 }; with(o1) { with(o2) { getScopeChain(); } }")); QCOMPARE(ret.size(), 3); QVERIFY(ret.at(2).strictlyEquals(eng.globalObject())); QVERIFY(ret.at(1).isObject()); QCOMPARE(ret.at(1).property("x").toInt32(), 123); QVERIFY(ret.at(0).isObject()); QCOMPARE(ret.at(0).property("y").toInt32(), 456); } }
void tst_QScriptContext::getSetActivationObject() { QScriptEngine eng; QScriptContext *ctx = eng.currentContext(); QVERIFY(ctx->activationObject().equals(eng.globalObject())); ctx->setActivationObject(QScriptValue()); QVERIFY(ctx->activationObject().equals(eng.globalObject())); QCOMPARE(ctx->engine(), &eng); QScriptValue obj = eng.newObject(); ctx->setActivationObject(obj); QVERIFY(ctx->activationObject().equals(obj)); QCOMPARE(ctx->scopeChain().size(), 1); QVERIFY(ctx->scopeChain().at(0).equals(obj)); { QScriptEngine eng2; QScriptValue obj2 = eng2.newObject(); QTest::ignoreMessage(QtWarningMsg, "QScriptContext::setActivationObject() failed: cannot set an object created in a different engine"); QScriptValue was = ctx->activationObject(); ctx->setActivationObject(obj2); QVERIFY(ctx->activationObject().equals(was)); } ctx->setActivationObject(eng.globalObject()); QVERIFY(ctx->activationObject().equals(eng.globalObject())); QScriptValue fun = eng.newFunction(get_activationObject); eng.globalObject().setProperty("get_activationObject", fun); { QScriptValue ret = eng.evaluate("get_activationObject(1, 2, 3)"); QVERIFY(ret.isObject()); QScriptValue arguments = ret.property("arguments"); QEXPECT_FAIL("", "Getting arguments property of activation object doesn't work", Abort); QVERIFY(arguments.isObject()); QCOMPARE(arguments.property("length").toInt32(), 3); QCOMPARE(arguments.property("0").toInt32(), 1); QCOMPARE(arguments.property("1").toInt32(), 1); QCOMPARE(arguments.property("2").toInt32(), 1); } }
void tst_QScriptContext::pushAndPopScope() { QScriptEngine eng; QScriptContext *ctx = eng.currentContext(); QCOMPARE(ctx->scopeChain().size(), 1); QVERIFY(ctx->scopeChain().at(0).strictlyEquals(eng.globalObject())); QVERIFY(ctx->popScope().strictlyEquals(eng.globalObject())); ctx->pushScope(eng.globalObject()); QCOMPARE(ctx->scopeChain().size(), 1); QVERIFY(ctx->scopeChain().at(0).strictlyEquals(eng.globalObject())); QScriptValue obj = eng.newObject(); ctx->pushScope(obj); QCOMPARE(ctx->scopeChain().size(), 2); QVERIFY(ctx->scopeChain().at(0).strictlyEquals(obj)); QVERIFY(ctx->scopeChain().at(1).strictlyEquals(eng.globalObject())); QVERIFY(ctx->popScope().strictlyEquals(obj)); QCOMPARE(ctx->scopeChain().size(), 1); QVERIFY(ctx->scopeChain().at(0).strictlyEquals(eng.globalObject())); { QScriptValue ret = eng.evaluate("x"); QVERIFY(ret.isError()); eng.clearExceptions(); } QCOMPARE(ctx->scopeChain().size(), 1); QVERIFY(ctx->scopeChain().at(0).strictlyEquals(eng.globalObject())); // task 236685 QScriptValue qobj = eng.newQObject(this, QScriptEngine::QtOwnership, QScriptEngine::AutoCreateDynamicProperties); ctx->pushScope(qobj); QCOMPARE(ctx->scopeChain().size(), 2); QVERIFY(ctx->scopeChain().at(0).strictlyEquals(qobj)); QVERIFY(ctx->scopeChain().at(1).strictlyEquals(eng.globalObject())); { QScriptValue ret = eng.evaluate("print"); QVERIFY(ret.isFunction()); } ctx->popScope(); ctx->pushScope(obj); QCOMPARE(ctx->scopeChain().size(), 2); QVERIFY(ctx->scopeChain().at(0).strictlyEquals(obj)); obj.setProperty("x", 123); { QScriptValue ret = eng.evaluate("x"); QVERIFY(ret.isNumber()); QCOMPARE(ret.toInt32(), 123); } QVERIFY(ctx->popScope().strictlyEquals(obj)); QCOMPARE(ctx->scopeChain().size(), 1); QVERIFY(ctx->scopeChain().at(0).strictlyEquals(eng.globalObject())); ctx->pushScope(QScriptValue()); QCOMPARE(ctx->scopeChain().size(), 1); QVERIFY(ctx->popScope().strictlyEquals(eng.globalObject())); QVERIFY(ctx->scopeChain().isEmpty()); // Used to work with old back-end, doesn't with new one because JSC requires that the last object in // a scope chain is the Global Object. QTest::ignoreMessage(QtWarningMsg, "QScriptContext::pushScope() failed: initial object in scope chain has to be the Global Object"); ctx->pushScope(obj); QCOMPARE(ctx->scopeChain().size(), 0); QScriptEngine eng2; QScriptValue obj2 = eng2.newObject(); QTest::ignoreMessage(QtWarningMsg, "QScriptContext::pushScope() failed: cannot push an object created in a different engine"); ctx->pushScope(obj2); QVERIFY(ctx->scopeChain().isEmpty()); QVERIFY(!ctx->popScope().isValid()); }
void tst_QScriptContext::pushAndPopContext() { QScriptEngine eng; QScriptContext *topLevel = eng.currentContext(); QCOMPARE(topLevel->engine(), &eng); QScriptContext *ctx = eng.pushContext(); QVERIFY(ctx != 0); QCOMPARE(ctx->parentContext(), topLevel); QCOMPARE(eng.currentContext(), ctx); QCOMPARE(ctx->engine(), &eng); QCOMPARE(ctx->state(), QScriptContext::NormalState); QCOMPARE(ctx->isCalledAsConstructor(), false); QCOMPARE(ctx->argumentCount(), 0); QCOMPARE(ctx->argument(0).isUndefined(), true); QVERIFY(!ctx->argument(-1).isValid()); QCOMPARE(ctx->argumentsObject().isObject(), true); QCOMPARE(ctx->activationObject().isObject(), true); QCOMPARE(ctx->callee().isValid(), false); QCOMPARE(ctx->thisObject().strictlyEquals(eng.globalObject()), true); QCOMPARE(ctx->scopeChain().size(), 2); QVERIFY(ctx->scopeChain().at(0).equals(ctx->activationObject())); QVERIFY(ctx->scopeChain().at(1).equals(eng.globalObject())); QScriptContext *ctx2 = eng.pushContext(); QCOMPARE(ctx2->parentContext(), ctx); QCOMPARE(eng.currentContext(), ctx2); eng.popContext(); QCOMPARE(eng.currentContext(), ctx); eng.popContext(); QCOMPARE(eng.currentContext(), topLevel); // popping the top-level context is not allowed QTest::ignoreMessage(QtWarningMsg, "QScriptEngine::popContext() doesn't match with pushContext()"); eng.popContext(); QCOMPARE(eng.currentContext(), topLevel); { QScriptContext *ctx3 = eng.pushContext(); ctx3->activationObject().setProperty("foo", QScriptValue(&eng, 123)); QVERIFY(eng.evaluate("foo").strictlyEquals(QScriptValue(&eng, 123))); eng.evaluate("var bar = 'ciao'"); QVERIFY(ctx3->activationObject().property("bar", QScriptValue::ResolveLocal).strictlyEquals(QScriptValue(&eng, "ciao"))); eng.popContext(); } { QScriptContext *ctx4 = eng.pushContext(); QScriptValue obj = eng.newObject(); obj.setProperty("prop", QScriptValue(&eng, 456)); ctx4->setThisObject(obj); QScriptValue ret = eng.evaluate("var tmp = this.prop; tmp + 1"); QCOMPARE(eng.currentContext(), ctx4); QVERIFY(ret.strictlyEquals(QScriptValue(&eng, 457))); eng.popContext(); } // throwing an exception { QScriptContext *ctx5 = eng.pushContext(); QScriptValue ret = eng.evaluate("throw new Error('oops')"); QVERIFY(ret.isError()); QVERIFY(eng.hasUncaughtException()); QCOMPARE(eng.currentContext(), ctx5); eng.popContext(); } }
void tst_QScriptContext::arguments() { QScriptEngine eng; { QScriptValue args = eng.currentContext()->argumentsObject(); QVERIFY(args.isObject()); QCOMPARE(args.property("length").toInt32(), 0); } { QScriptValue fun = eng.newFunction(get_arguments); eng.globalObject().setProperty("get_arguments", fun); } for (int x = 0; x < 2; ++x) { QString prefix; if (x == 0) prefix = ""; else prefix = "new "; { QScriptValue result = eng.evaluate(prefix+"get_arguments()"); QCOMPARE(result.isArray(), true); QCOMPARE(result.property("length").toUInt32(), quint32(0)); } { QScriptValue result = eng.evaluate(prefix+"get_arguments(123)"); QCOMPARE(result.isArray(), true); QCOMPARE(result.property("length").toUInt32(), quint32(1)); QCOMPARE(result.property("0").isNumber(), true); QCOMPARE(result.property("0").toNumber(), 123.0); } { QScriptValue result = eng.evaluate(prefix+"get_arguments(\"ciao\", null, true, undefined)"); QCOMPARE(result.isArray(), true); QCOMPARE(result.property("length").toUInt32(), quint32(4)); QCOMPARE(result.property("0").isString(), true); QCOMPARE(result.property("0").toString(), QString("ciao")); QCOMPARE(result.property("1").isNull(), true); QCOMPARE(result.property("2").isBoolean(), true); QCOMPARE(result.property("2").toBoolean(), true); QCOMPARE(result.property("3").isUndefined(), true); } { QScriptValue fun = eng.newFunction(get_argumentsObject); eng.globalObject().setProperty("get_argumentsObject", fun); } { QScriptValue fun = eng.evaluate("get_argumentsObject"); QCOMPARE(fun.isFunction(), true); QScriptValue result = eng.evaluate(prefix+"get_argumentsObject()"); QCOMPARE(result.isArray(), false); QVERIFY(result.isObject()); QCOMPARE(result.property("length").toUInt32(), quint32(0)); QCOMPARE(result.propertyFlags("length"), QScriptValue::SkipInEnumeration); QCOMPARE(result.property("callee").strictlyEquals(fun), true); QCOMPARE(result.propertyFlags("callee"), QScriptValue::SkipInEnumeration); QScriptValue replacedCallee(&eng, 123); result.setProperty("callee", replacedCallee); QVERIFY(result.property("callee").equals(replacedCallee)); QScriptValue replacedLength(&eng, 456); result.setProperty("length", replacedLength); QVERIFY(result.property("length").equals(replacedLength)); result.setProperty("callee", QScriptValue()); QVERIFY(!result.property("callee").isValid()); result.setProperty("length", QScriptValue()); QVERIFY(!result.property("length").isValid()); } { QScriptValue result = eng.evaluate(prefix+"get_argumentsObject(123)"); eng.evaluate("function nestedArg(x,y,z) { var w = get_argumentsObject('ABC' , x+y+z); return w; }"); QScriptValue result2 = eng.evaluate("nestedArg(1, 'a', 2)"); QCOMPARE(result.isArray(), false); QVERIFY(result.isObject()); QCOMPARE(result.property("length").toUInt32(), quint32(1)); QCOMPARE(result.property("0").isNumber(), true); QCOMPARE(result.property("0").toNumber(), 123.0); QVERIFY(result2.isObject()); QCOMPARE(result2.property("length").toUInt32(), quint32(2)); QCOMPARE(result2.property("0").toString(), QString::fromLatin1("ABC")); QCOMPARE(result2.property("1").toString(), QString::fromLatin1("1a2")); } { QScriptValue result = eng.evaluate(prefix+"get_argumentsObject(\"ciao\", null, true, undefined)"); QCOMPARE(result.isArray(), false); QCOMPARE(result.property("length").toUInt32(), quint32(4)); QCOMPARE(result.property("0").isString(), true); QCOMPARE(result.property("0").toString(), QString("ciao")); QCOMPARE(result.property("1").isNull(), true); QCOMPARE(result.property("2").isBoolean(), true); QCOMPARE(result.property("2").toBoolean(), true); QCOMPARE(result.property("3").isUndefined(), true); } // arguments object returned from script { QScriptValue result = eng.evaluate("(function() { return arguments; })(123)"); QCOMPARE(result.isArray(), false); QVERIFY(result.isObject()); QCOMPARE(result.property("length").toUInt32(), quint32(1)); QCOMPARE(result.property("0").isNumber(), true); QCOMPARE(result.property("0").toNumber(), 123.0); } { QScriptValue result = eng.evaluate("(function() { return arguments; })('ciao', null, true, undefined)"); QCOMPARE(result.isArray(), false); QCOMPARE(result.property("length").toUInt32(), quint32(4)); QCOMPARE(result.property("0").isString(), true); QCOMPARE(result.property("0").toString(), QString("ciao")); QCOMPARE(result.property("1").isNull(), true); QCOMPARE(result.property("2").isBoolean(), true); QCOMPARE(result.property("2").toBoolean(), true); QCOMPARE(result.property("3").isUndefined(), true); } } }