diff options
-rw-r--r-- | src/script/api/qscriptengine.cpp | 34 | ||||
-rw-r--r-- | src/script/api/qscriptengine_p.h | 5 | ||||
-rw-r--r-- | src/script/api/qscriptengineagent.cpp | 2 | ||||
-rw-r--r-- | tests/auto/qscriptengine/tst_qscriptengine.cpp | 36 |
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() |