summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/script/api/qscriptengine.cpp34
-rw-r--r--src/script/api/qscriptengine_p.h5
-rw-r--r--src/script/api/qscriptengineagent.cpp2
-rw-r--r--tests/auto/qscriptengine/tst_qscriptengine.cpp36
4 files changed, 62 insertions, 15 deletions
diff --git a/src/script/api/qscriptengine.cpp b/src/script/api/qscriptengine.cpp
index 63041db..02293ea 100644
--- a/src/script/api/qscriptengine.cpp
+++ b/src/script/api/qscriptengine.cpp
@@ -828,12 +828,14 @@ QScriptEnginePrivate::QScriptEnginePrivate() : idGenerator(1)
currentFrame = exec;
originalGlobalObjectProxy = 0;
- agent = 0;
+ activeAgent = 0;
processEventsInterval = -1;
}
QScriptEnginePrivate::~QScriptEnginePrivate()
{
+ while (!ownedAgents.isEmpty())
+ delete ownedAgents.takeFirst();
detachAllRegisteredScriptValues();
qDeleteAll(m_qobjectData);
qDeleteAll(m_typeInfos);
@@ -1189,6 +1191,15 @@ QScript::TimeoutCheckerProxy *QScriptEnginePrivate::timeoutChecker() const
return static_cast<QScript::TimeoutCheckerProxy*>(globalData->timeoutChecker);
}
+void QScriptEnginePrivate::agentDeleted(QScriptEngineAgent *agent)
+{
+ ownedAgents.removeOne(agent);
+ if (activeAgent == agent) {
+ QScriptEngineAgentPrivate::get(agent)->detach();
+ activeAgent = 0;
+ }
+}
+
#ifndef QT_NO_QOBJECT
JSC::JSValue QScriptEnginePrivate::newQObject(
@@ -3603,11 +3614,20 @@ QT_END_INCLUDE_NAMESPACE
void QScriptEngine::setAgent(QScriptEngineAgent *agent)
{
Q_D(QScriptEngine);
- if (d->agent)
- QScriptEngineAgentPrivate::get(d->agent)->detach();
- d->agent = agent;
- if (agent)
- QScriptEngineAgentPrivate::get(d->agent)->attach();
+ if (agent && (agent->engine() != this)) {
+ qWarning("QScriptEngine::setAgent(): "
+ "cannot set agent belonging to different engine");
+ return;
+ }
+ if (d->activeAgent)
+ QScriptEngineAgentPrivate::get(d->activeAgent)->detach();
+ d->activeAgent = agent;
+ if (agent) {
+ int index = d->ownedAgents.indexOf(agent);
+ if (index == -1)
+ d->ownedAgents.append(agent);
+ QScriptEngineAgentPrivate::get(agent)->attach();
+ }
}
/*!
@@ -3621,7 +3641,7 @@ void QScriptEngine::setAgent(QScriptEngineAgent *agent)
QScriptEngineAgent *QScriptEngine::agent() const
{
Q_D(const QScriptEngine);
- return d->agent;
+ return d->activeAgent;
}
/*!
diff --git a/src/script/api/qscriptengine_p.h b/src/script/api/qscriptengine_p.h
index 53972a2..3a5c79d 100644
--- a/src/script/api/qscriptengine_p.h
+++ b/src/script/api/qscriptengine_p.h
@@ -174,6 +174,8 @@ public:
QScript::TimeoutCheckerProxy *timeoutChecker() const;
+ void agentDeleted(QScriptEngineAgent *agent);
+
#ifndef QT_NO_QOBJECT
JSC::JSValue newQObject(QObject *object,
QScriptEngine::ValueOwnership ownership = QScriptEngine::QtOwnership,
@@ -235,7 +237,8 @@ public:
QScript::QVariantPrototype *variantPrototype;
WTF::RefPtr<JSC::Structure> variantWrapperObjectStructure;
- QScriptEngineAgent *agent;
+ QList<QScriptEngineAgent*> ownedAgents;
+ QScriptEngineAgent *activeAgent;
QHash<JSC::JSCell*, QBasicAtomicInt> keepAliveValues;
QHash<int, QScriptTypeInfo*> m_typeInfos;
int processEventsInterval;
diff --git a/src/script/api/qscriptengineagent.cpp b/src/script/api/qscriptengineagent.cpp
index 9c352ad..4f89e81 100644
--- a/src/script/api/qscriptengineagent.cpp
+++ b/src/script/api/qscriptengineagent.cpp
@@ -205,6 +205,8 @@ QScriptEngineAgent::QScriptEngineAgent(QScriptEngineAgentPrivate &dd, QScriptEng
*/
QScriptEngineAgent::~QScriptEngineAgent()
{
+ QScriptEnginePrivate *eng_p = QScriptEnginePrivate::get(engine());
+ eng_p->agentDeleted(this);
delete d_ptr;
d_ptr = 0;
}
diff --git a/tests/auto/qscriptengine/tst_qscriptengine.cpp b/tests/auto/qscriptengine/tst_qscriptengine.cpp
index eb24616..cf6ebd8 100644
--- a/tests/auto/qscriptengine/tst_qscriptengine.cpp
+++ b/tests/auto/qscriptengine/tst_qscriptengine.cpp
@@ -3649,13 +3649,35 @@ public:
void tst_QScriptEngine::getSetAgent()
{
- QScriptEngine eng;
- QCOMPARE(eng.agent(), (QScriptEngineAgent*)0);
- TestAgent agent(&eng);
- eng.setAgent(&agent);
- QCOMPARE(eng.agent(), (QScriptEngineAgent*)&agent);
- eng.setAgent(0);
- QCOMPARE(eng.agent(), (QScriptEngineAgent*)0);
+ // case 1: engine deleted before agent --> agent deleted too
+ {
+ QScriptEngine *eng = new QScriptEngine;
+ QCOMPARE(eng->agent(), (QScriptEngineAgent*)0);
+ TestAgent *agent = new TestAgent(eng);
+ eng->setAgent(agent);
+ QCOMPARE(eng->agent(), (QScriptEngineAgent*)agent);
+ eng->setAgent(0); // the engine maintains ownership of the old agent
+ QCOMPARE(eng->agent(), (QScriptEngineAgent*)0);
+ delete eng;
+ }
+ // case 2: agent deleted before engine --> engine's agent should become 0
+ {
+ QScriptEngine *eng = new QScriptEngine;
+ TestAgent *agent = new TestAgent(eng);
+ eng->setAgent(agent);
+ QCOMPARE(eng->agent(), (QScriptEngineAgent*)agent);
+ delete agent;
+ QCOMPARE(eng->agent(), (QScriptEngineAgent*)0);
+ eng->evaluate("(function(){ return 123; })()");
+ delete eng;
+ }
+ {
+ QScriptEngine eng;
+ QScriptEngine eng2;
+ TestAgent *agent = new TestAgent(&eng);
+ QTest::ignoreMessage(QtWarningMsg, "QScriptEngine::setAgent(): cannot set agent belonging to different engine");
+ eng2.setAgent(agent);
+ }
}
void tst_QScriptEngine::reentrancy()