summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAaron Kennedy <aaron.kennedy@nokia.com>2011-02-14 04:25:15 (GMT)
committerAaron Kennedy <aaron.kennedy@nokia.com>2011-02-14 04:36:57 (GMT)
commit3bc6f8d8dd630cd0298e27fc4b7430d2bf73a232 (patch)
tree55b7099a9044efb8182323fd67841b95616d82f7
parent2855782a45b08aedbed960125514fdd9663ff1c8 (diff)
downloadQt-3bc6f8d8dd630cd0298e27fc4b7430d2bf73a232.zip
Qt-3bc6f8d8dd630cd0298e27fc4b7430d2bf73a232.tar.gz
Qt-3bc6f8d8dd630cd0298e27fc4b7430d2bf73a232.tar.bz2
Don't leak ScopeChainNode's
Create a sub-scope of the global scope chain, rather than a completely new scope chain. Leaks are difficult to autotest, but an autotest for QScriptDeclarativeClass::pushCleanContext() was added to ensure its behavior doesn't regress. To reproduce the leak (prior to this change) use: while (true) { QScriptDeclarativeClass::pushCleanContext(&engine); engine.popContext(); } Change-Id: I41ac61ea1664da569eb329c8276f2a0bb6d2f1f7 Task-number: QTBUG-17166 Reviewed-by: Martin Jones
-rw-r--r--src/script/api/qscriptengine.cpp4
-rw-r--r--tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp40
2 files changed, 41 insertions, 3 deletions
diff --git a/src/script/api/qscriptengine.cpp b/src/script/api/qscriptengine.cpp
index 54039c0..e58c43b 100644
--- a/src/script/api/qscriptengine.cpp
+++ b/src/script/api/qscriptengine.cpp
@@ -2761,9 +2761,7 @@ JSC::CallFrame *QScriptEnginePrivate::pushContext(JSC::CallFrame *exec, JSC::JSV
if (!clearScopeChain) {
newCallFrame->init(0, /*vPC=*/0, exec->scopeChain(), exec, flags | ShouldRestoreCallFrame, argc, callee);
} else {
- JSC::JSObject *jscObject = originalGlobalObject();
- JSC::ScopeChainNode *scn = new JSC::ScopeChainNode(0, jscObject, &exec->globalData(), exec->lexicalGlobalObject(), jscObject);
- newCallFrame->init(0, /*vPC=*/0, scn, exec, flags | ShouldRestoreCallFrame, argc, callee);
+ newCallFrame->init(0, /*vPC=*/0, globalExec()->scopeChain(), exec, flags | ShouldRestoreCallFrame, argc, callee);
}
} else {
setContextFlags(newCallFrame, flags);
diff --git a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp
index b19b3c9..40b0e1b 100644
--- a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp
+++ b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp
@@ -50,6 +50,7 @@
#include <QtCore/qnumeric.h>
#include <private/qdeclarativeengine_p.h>
#include <private/qdeclarativeglobalscriptclass_p.h>
+#include <private/qscriptdeclarativeclass_p.h>
#include "testtypes.h"
#include "testhttpserver.h"
#include "../../../shared/util.h"
@@ -174,6 +175,7 @@ private slots:
void aliasBindingsAssignCorrectly();
void aliasBindingsOverrideTarget();
void aliasWritesOverrideBindings();
+ void pushCleanContext();
void include();
@@ -3015,6 +3017,44 @@ void tst_qdeclarativeecmascript::revision()
}
}
+// Test for QScriptDeclarativeClass::pushCleanContext()
+void tst_qdeclarativeecmascript::pushCleanContext()
+{
+ QScriptEngine engine;
+ engine.globalObject().setProperty("a", 6);
+ QCOMPARE(engine.evaluate("a").toInt32(), 6);
+
+ // First confirm pushContext() behaves as we expect
+ QScriptValue object = engine.newObject();
+ object.setProperty("a", 15);
+ QScriptContext *context1 = engine.pushContext();
+ context1->pushScope(object);
+ QCOMPARE(engine.evaluate("a").toInt32(), 15);
+
+ QScriptContext *context2 = engine.pushContext();
+ Q_UNUSED(context2);
+ QCOMPARE(engine.evaluate("a").toInt32(), 15);
+ QScriptValue func1 = engine.evaluate("(function() { return a; })");
+
+ // Now check that pushCleanContext() works
+ QScriptDeclarativeClass::pushCleanContext(&engine);
+ QCOMPARE(engine.evaluate("a").toInt32(), 6);
+ QScriptValue func2 = engine.evaluate("(function() { return a; })");
+
+ engine.popContext();
+ QCOMPARE(engine.evaluate("a").toInt32(), 15);
+
+ engine.popContext();
+ QCOMPARE(engine.evaluate("a").toInt32(), 15);
+
+ engine.popContext();
+ QCOMPARE(engine.evaluate("a").toInt32(), 6);
+
+ // Check that function objects created in these contexts work
+ QCOMPARE(func1.call().toInt32(), 15);
+ QCOMPARE(func2.call().toInt32(), 6);
+}
+
QTEST_MAIN(tst_qdeclarativeecmascript)
#include "tst_qdeclarativeecmascript.moc"