summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJedrzej Nowacki <jedrzej.nowacki@nokia.com>2010-09-30 13:17:39 +0200
committerSamuli Piippo <samuli.piippo@digia.com>2011-06-09 13:07:01 +0300
commitf955d645ff3804aa8544f94d02175deec7a0d873 (patch)
tree786215c7cc684d1e411574c7c9fbecaa4b0eb167
parentd0be1ef82ecd3ab6a8195fd9bceeecfa470877f9 (diff)
Fix QScriptEngine::abortEvaluation.
This patch reduce time in which QScriptEngine would abort an script executing multiple long-running native functions. Task-number: QTBUG-9433 Reviewed-by: Olivier Goffart (cherry picked from commit eb407209bb9f2c06684fd1299169cd3b8ab4b58d)
-rw-r--r--src/script/api/qscriptengine.cpp7
-rw-r--r--tests/auto/qscriptengine/tst_qscriptengine.cpp60
2 files changed, 62 insertions, 5 deletions
diff --git a/src/script/api/qscriptengine.cpp b/src/script/api/qscriptengine.cpp
index f44f33d564..91c06f645a 100644
--- a/src/script/api/qscriptengine.cpp
+++ b/src/script/api/qscriptengine.cpp
@@ -49,6 +49,7 @@
#include "DateConstructor.h"
#include "RegExpConstructor.h"
+#include "ExceptionHelpers.h"
#include "PrototypeFunction.h"
#include "InitializeThreading.h"
#include "ObjectPrototype.h"
@@ -3547,9 +3548,11 @@ bool QScriptEngine::isEvaluating() const
void QScriptEngine::abortEvaluation(const QScriptValue &result)
{
Q_D(QScriptEngine);
-
- d->timeoutChecker()->setShouldAbort(true);
+ if (!isEvaluating())
+ return;
d->abortResult = result;
+ d->timeoutChecker()->setShouldAbort(true);
+ JSC::throwError(d->currentFrame, JSC::createInterruptedExecutionException(&d->currentFrame->globalData()).toObject(d->currentFrame));
}
#ifndef QT_NO_QOBJECT
diff --git a/tests/auto/qscriptengine/tst_qscriptengine.cpp b/tests/auto/qscriptengine/tst_qscriptengine.cpp
index 47ca598414..57aca7b8cd 100644
--- a/tests/auto/qscriptengine/tst_qscriptengine.cpp
+++ b/tests/auto/qscriptengine/tst_qscriptengine.cpp
@@ -131,6 +131,7 @@ private slots:
void numberParsing();
void automaticSemicolonInsertion();
void abortEvaluation();
+ void abortEvaluation_QTBUG9433();
void isEvaluating();
void printFunctionWithCustomHandler();
void printThrowsException();
@@ -2977,7 +2978,8 @@ public:
enum AbortionResult {
None = 0,
String = 1,
- Error = 2
+ Error = 2,
+ Number = 3
};
EventReceiver3(QScriptEngine *eng) {
@@ -2997,6 +2999,8 @@ public:
case Error:
engine->abortEvaluation(engine->currentContext()->throwError("AbortedWithError"));
break;
+ case Number:
+ engine->abortEvaluation(QScriptValue(1234));
}
}
return QObject::event(e);
@@ -3029,7 +3033,7 @@ void tst_QScriptEngine::abortEvaluation()
EventReceiver3 receiver(&eng);
eng.setProcessEventsInterval(100);
- for (int x = 0; x < 3; ++x) {
+ for (int x = 0; x < 4; ++x) {
QCoreApplication::postEvent(&receiver, new QEvent(QEvent::Type(QEvent::User+1)));
receiver.resultType = EventReceiver3::AbortionResult(x);
QScriptValue ret = eng.evaluate(QString::fromLatin1("while (1) { }"));
@@ -3038,6 +3042,11 @@ void tst_QScriptEngine::abortEvaluation()
QVERIFY(!eng.hasUncaughtException());
QVERIFY(!ret.isValid());
break;
+ case EventReceiver3::Number:
+ QVERIFY(!eng.hasUncaughtException());
+ QVERIFY(ret.isNumber());
+ QCOMPARE(ret.toInt32(), 1234);
+ break;
case EventReceiver3::String:
QVERIFY(!eng.hasUncaughtException());
QVERIFY(ret.isString());
@@ -3052,7 +3061,7 @@ void tst_QScriptEngine::abortEvaluation()
}
// scripts cannot intercept the abortion with try/catch
- for (int y = 0; y < 3; ++y) {
+ for (int y = 0; y < 4; ++y) {
QCoreApplication::postEvent(&receiver, new QEvent(QEvent::Type(QEvent::User+1)));
receiver.resultType = EventReceiver3::AbortionResult(y);
QScriptValue ret = eng.evaluate(QString::fromLatin1(
@@ -3068,6 +3077,11 @@ void tst_QScriptEngine::abortEvaluation()
QVERIFY(!eng.hasUncaughtException());
QVERIFY(!ret.isValid());
break;
+ case EventReceiver3::Number:
+ QVERIFY(!eng.hasUncaughtException());
+ QVERIFY(ret.isNumber());
+ QCOMPARE(ret.toInt32(), 1234);
+ break;
case EventReceiver3::String:
QVERIFY(!eng.hasUncaughtException());
QVERIFY(ret.isString());
@@ -3088,6 +3102,46 @@ void tst_QScriptEngine::abortEvaluation()
}
}
+class ThreadedEngine : public QThread {
+ Q_OBJECT;
+
+private:
+ QScriptEngine* m_engine;
+protected:
+ void run() {
+ m_engine = new QScriptEngine();
+ m_engine->setGlobalObject(m_engine->newQObject(this));
+ m_engine->evaluate("while(1) { sleep(); }");
+ delete m_engine;
+ }
+
+public slots:
+ void sleep()
+ {
+ QTest::qSleep(25);
+ m_engine->abortEvaluation();
+ }
+};
+
+void tst_QScriptEngine::abortEvaluation_QTBUG9433()
+{
+ ThreadedEngine engine;
+ engine.start();
+ QVERIFY(engine.isRunning());
+ QTest::qSleep(50);
+ for (uint i = 0; i < 50; ++i) { // up to ~2500 ms
+ if (engine.isFinished())
+ return;
+ QTest::qSleep(50);
+ }
+ if (!engine.isFinished()) {
+ engine.terminate();
+ engine.wait(7000);
+ QFAIL("abortEvaluation doesn't work");
+ }
+
+}
+
static QScriptValue myFunctionReturningIsEvaluating(QScriptContext *, QScriptEngine *eng)
{
return QScriptValue(eng, eng->isEvaluating());