aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime
diff options
context:
space:
mode:
authorErik Verbruggen <erik.verbruggen@digia.com>2014-07-04 17:01:02 +0200
committerErik Verbruggen <erik.verbruggen@digia.com>2014-08-08 10:45:12 +0200
commit6333e0913fc0078c0221a8909ced8df03a568992 (patch)
tree40661d956eb9a87ba3f695811de0e3c591ab7583 /src/qml/jsruntime
parent94669499fd943fc72095afd739a21cd8e675f14f (diff)
Add support for conditional breakpoints and evaluate.
Also centralized the context state saver and added line number saving, so that the JS jobs for evaluation of breakpoint conditions don't change the state of the current engine context. Task-number: QTBUG-37119 Task-number: QTCREATORBUG-11516 Change-Id: Ia21b3d64e239e5b67f3c07e1c006d8e6748f29b6 Reviewed-by: Erik Verbruggen <erik.verbruggen@digia.com> Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
Diffstat (limited to 'src/qml/jsruntime')
-rw-r--r--src/qml/jsruntime/qv4debugging.cpp80
-rw-r--r--src/qml/jsruntime/qv4debugging_p.h2
-rw-r--r--src/qml/jsruntime/qv4globalobject.cpp21
-rw-r--r--src/qml/jsruntime/qv4script.cpp21
-rw-r--r--src/qml/jsruntime/qv4script_p.h24
5 files changed, 98 insertions, 50 deletions
diff --git a/src/qml/jsruntime/qv4debugging.cpp b/src/qml/jsruntime/qv4debugging.cpp
index 04422b9f5e..78de614664 100644
--- a/src/qml/jsruntime/qv4debugging.cpp
+++ b/src/qml/jsruntime/qv4debugging.cpp
@@ -45,6 +45,7 @@
#include "qv4function_p.h"
#include "qv4instr_moth_p.h"
#include "qv4runtime_p.h"
+#include "qv4script_p.h"
#include <iostream>
#include <algorithm>
@@ -53,29 +54,74 @@ using namespace QV4;
using namespace QV4::Debugging;
namespace {
-class EvalJob: public Debugger::Job
+class JavaScriptJob: public Debugger::Job
{
QV4::ExecutionEngine *engine;
const QString &script;
public:
- EvalJob(QV4::ExecutionEngine *engine, const QString &script)
+ JavaScriptJob(QV4::ExecutionEngine *engine, const QString &script)
: engine(engine)
, script(script)
{}
- ~EvalJob() {}
-
void run()
{
- // TODO
- qDebug() << "Evaluating script:" << script;
- Q_UNUSED(engine);
+ QV4::Scope scope(engine);
+ QV4::ExecutionContext *ctx = engine->currentContext();
+ ContextStateSaver ctxSaver(ctx);
+ QV4::ScopedValue result(scope);
+
+ QV4::Script script(ctx, this->script);
+ script.strictMode = ctx->d()->strictMode;
+ script.inheritContext = false;
+ script.parse();
+ if (!scope.engine->hasException)
+ result = script.run();
+ if (scope.engine->hasException)
+ result = ctx->catchException();
+ handleResult(result);
+ }
+
+protected:
+ virtual void handleResult(QV4::ScopedValue &result) = 0;
+};
+
+class EvalJob: public JavaScriptJob
+{
+ bool result;
+
+public:
+ EvalJob(QV4::ExecutionEngine *engine, const QString &script)
+ : JavaScriptJob(engine, script)
+ , result(false)
+ {}
+
+ virtual void handleResult(QV4::ScopedValue &result)
+ {
+ this->result = result->toBoolean();
}
bool resultAsBoolean() const
{
- return true;
+ return result;
+ }
+};
+
+class ExpressionEvalJob: public JavaScriptJob
+{
+ Debugger::Collector *collector;
+
+public:
+ ExpressionEvalJob(ExecutionEngine *engine, const QString &expression, Debugger::Collector *collector)
+ : JavaScriptJob(engine, expression)
+ , collector(collector)
+ {
+ }
+
+ virtual void handleResult(QV4::ScopedValue &result)
+ {
+ collector->collect(QStringLiteral("body"), result);
}
};
@@ -444,6 +490,19 @@ QVector<ExecutionContext::ContextType> Debugger::getScopeTypes(int frame) const
return types;
}
+
+void Debugger::evaluateExpression(int frameNr, const QString &expression, Debugger::Collector *resultsCollector)
+{
+ Q_ASSERT(state() == Paused);
+ Q_UNUSED(frameNr);
+
+ Q_ASSERT(m_runningJob == 0);
+ ExpressionEvalJob job(m_engine, expression, resultsCollector);
+ m_runningJob = &job;
+ m_runningJob->run();
+ m_runningJob = 0;
+}
+
void Debugger::maybeBreakAtInstruction()
{
if (m_runningJob) // do not re-enter when we're doing a job for the debugger.
@@ -481,6 +540,8 @@ void Debugger::maybeBreakAtInstruction()
void Debugger::enteringFunction()
{
+ if (m_runningJob)
+ return;
QMutexLocker locker(&m_lock);
if (m_stepping == StepIn) {
@@ -490,6 +551,8 @@ void Debugger::enteringFunction()
void Debugger::leavingFunction(const ReturnedValue &retVal)
{
+ if (m_runningJob)
+ return;
Q_UNUSED(retVal); // TODO
QMutexLocker locker(&m_lock);
@@ -560,6 +623,7 @@ bool Debugger::reallyHitTheBreakPoint(const QString &filename, int linenr)
EvalJob evilJob(m_engine, condition);
m_runningJob = &evilJob;
m_runningJob->run();
+ m_runningJob = 0;
return evilJob.resultAsBoolean();
}
diff --git a/src/qml/jsruntime/qv4debugging_p.h b/src/qml/jsruntime/qv4debugging_p.h
index f834b8d15f..cedfee7f90 100644
--- a/src/qml/jsruntime/qv4debugging_p.h
+++ b/src/qml/jsruntime/qv4debugging_p.h
@@ -181,6 +181,8 @@ public:
void collectReturnedValue(Collector *collector) const;
QVector<ExecutionContext::ContextType> getScopeTypes(int frame = 0) const;
+ void evaluateExpression(int frameNr, const QString &expression, Collector *resultsCollector);
+
public: // compile-time interface
void maybeBreakAtInstruction();
diff --git a/src/qml/jsruntime/qv4globalobject.cpp b/src/qml/jsruntime/qv4globalobject.cpp
index fc4a097915..a699442273 100644
--- a/src/qml/jsruntime/qv4globalobject.cpp
+++ b/src/qml/jsruntime/qv4globalobject.cpp
@@ -357,27 +357,6 @@ EvalFunction::Data::Data(ExecutionContext *scope)
ReturnedValue EvalFunction::evalCall(CallData *callData, bool directCall)
{
- struct ContextStateSaver {
- ExecutionContext *savedContext;
- bool strictMode;
- ExecutionContext::EvalCode *evalCode;
- CompiledData::CompilationUnit *compilationUnit;
-
- ContextStateSaver(ExecutionContext *context)
- : savedContext(context)
- , strictMode(context->d()->strictMode)
- , evalCode(context->d()->currentEvalCode)
- , compilationUnit(context->d()->compilationUnit)
- {}
-
- ~ContextStateSaver()
- {
- savedContext->d()->strictMode = strictMode;
- savedContext->d()->currentEvalCode = evalCode;
- savedContext->d()->compilationUnit = compilationUnit;
- }
- };
-
if (callData->argc < 1)
return Encode::undefined();
diff --git a/src/qml/jsruntime/qv4script.cpp b/src/qml/jsruntime/qv4script.cpp
index e08a63bd1f..27bb7c8d2f 100644
--- a/src/qml/jsruntime/qv4script.cpp
+++ b/src/qml/jsruntime/qv4script.cpp
@@ -287,27 +287,6 @@ void Script::parse()
ReturnedValue Script::run()
{
- struct ContextStateSaver {
- ExecutionContext *savedContext;
- bool strictMode;
- Lookup *lookups;
- CompiledData::CompilationUnit *compilationUnit;
-
- ContextStateSaver(ExecutionContext *context)
- : savedContext(context)
- , strictMode(context->d()->strictMode)
- , lookups(context->d()->lookups)
- , compilationUnit(context->d()->compilationUnit)
- {}
-
- ~ContextStateSaver()
- {
- savedContext->d()->strictMode = strictMode;
- savedContext->d()->lookups = lookups;
- savedContext->d()->compilationUnit = compilationUnit;
- }
- };
-
if (!parsed)
parse();
if (!vmFunction)
diff --git a/src/qml/jsruntime/qv4script_p.h b/src/qml/jsruntime/qv4script_p.h
index 6a749d1438..6f947cd430 100644
--- a/src/qml/jsruntime/qv4script_p.h
+++ b/src/qml/jsruntime/qv4script_p.h
@@ -55,6 +55,30 @@ namespace QV4 {
struct ExecutionContext;
+struct ContextStateSaver {
+ ExecutionContext *savedContext;
+ bool strictMode;
+ Lookup *lookups;
+ CompiledData::CompilationUnit *compilationUnit;
+ int lineNumber;
+
+ ContextStateSaver(ExecutionContext *context)
+ : savedContext(context)
+ , strictMode(context->d()->strictMode)
+ , lookups(context->d()->lookups)
+ , compilationUnit(context->d()->compilationUnit)
+ , lineNumber(context->d()->lineNumber)
+ {}
+
+ ~ContextStateSaver()
+ {
+ savedContext->d()->strictMode = strictMode;
+ savedContext->d()->lookups = lookups;
+ savedContext->d()->compilationUnit = compilationUnit;
+ savedContext->d()->lineNumber = lineNumber;
+ }
+};
+
struct Q_QML_EXPORT QmlBindingWrapper : FunctionObject {
struct Data : FunctionObject::Data {
Data(ExecutionContext *scope, Function *f, Object *qml);