JSDebugger: Enable break on events.

The user can request Javascript break on event. The user can provide
this info in the Breakpoints Window and provide the slot which will
be called when the event occurs. For example: specify "onTriggered" if
you need to break on Timer triggered event.

Change-Id: If936d7402f5978a182132fdcca75515588364e16
Reviewed-on: http://codereview.qt-project.org/4758
Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com>
Reviewed-by: Kai Koehne <kai.koehne@nokia.com>
This commit is contained in:
Aurindam Jana
2011-09-13 12:47:46 +02:00
parent 1285a63852
commit f05683ac7e
13 changed files with 76 additions and 27 deletions

View File

@@ -122,6 +122,8 @@ static QString typeToString(BreakpointType type)
return BreakHandler::tr("Watchpoint at Address"); return BreakHandler::tr("Watchpoint at Address");
case WatchpointAtExpression: case WatchpointAtExpression:
return BreakHandler::tr("Watchpoint at Expression"); return BreakHandler::tr("Watchpoint at Expression");
case BreakpointOnSignalHandler:
return BreakHandler::tr("Breakpoint on Signal Handler");
case UnknownType: case UnknownType:
break; break;
} }

View File

@@ -260,6 +260,7 @@ QString BreakpointParameters::toString() const
<< " PathUsage: " << pathUsage; << " PathUsage: " << pathUsage;
break; break;
case BreakpointByFunction: case BreakpointByFunction:
case BreakpointOnSignalHandler:
ts << " FunctionName: " << functionName; ts << " FunctionName: " << functionName;
break; break;
case BreakpointByAddress: case BreakpointByAddress:

View File

@@ -139,7 +139,8 @@ enum BreakpointType
//BreakpointAtVFork, //BreakpointAtVFork,
BreakpointAtSysCall, BreakpointAtSysCall,
WatchpointAtAddress, WatchpointAtAddress,
WatchpointAtExpression WatchpointAtExpression,
BreakpointOnSignalHandler
}; };
//! \enum Debugger::Internal::BreakpointState //! \enum Debugger::Internal::BreakpointState

View File

@@ -119,8 +119,10 @@ BreakpointDialog::BreakpointDialog(unsigned engineCapabilities, QWidget *parent)
<< tr("Break when a new process is executed") << tr("Break when a new process is executed")
<< tr("Break when a system call is executed") << tr("Break when a system call is executed")
<< tr("Break on data access at fixed address") << tr("Break on data access at fixed address")
<< tr("Break on data access at address given by expression"); << tr("Break on data access at address given by expression")
QTC_ASSERT(types.size() == WatchpointAtExpression, return; ) << tr("Break on QML signal handler");
QTC_ASSERT(types.size() == BreakpointOnSignalHandler, return; )
m_ui.comboBoxType->addItems(types); m_ui.comboBoxType->addItems(types);
m_ui.pathChooserFileName->setExpectedKind(Utils::PathChooser::File); m_ui.pathChooserFileName->setExpectedKind(Utils::PathChooser::File);
connect(m_ui.comboBoxType, SIGNAL(activated(int)), SLOT(typeChanged(int))); connect(m_ui.comboBoxType, SIGNAL(activated(int)), SLOT(typeChanged(int)));
@@ -358,6 +360,8 @@ void BreakpointDialog::typeChanged(int)
case WatchpointAtExpression: case WatchpointAtExpression:
getParts(ExpressionPart|AllConditionParts|TracePointPart, &m_savedParameters); getParts(ExpressionPart|AllConditionParts|TracePointPart, &m_savedParameters);
break; break;
case BreakpointOnSignalHandler:
getParts(FunctionPart, &m_savedParameters);
} }
// Enable and set up new state from saved values. // Enable and set up new state from saved values.
@@ -399,6 +403,10 @@ void BreakpointDialog::typeChanged(int)
setPartsEnabled(ExpressionPart|AllConditionParts|TracePointPart|TracePointPart); setPartsEnabled(ExpressionPart|AllConditionParts|TracePointPart|TracePointPart);
clearOtherParts(ExpressionPart|AllConditionParts|TracePointPart); clearOtherParts(ExpressionPart|AllConditionParts|TracePointPart);
break; break;
case BreakpointOnSignalHandler:
setParts(FunctionPart, m_savedParameters);
setPartsEnabled(FunctionPart);
clearOtherParts(FunctionPart);
} }
} }

View File

@@ -2552,6 +2552,7 @@ bool CdbEngine::acceptsBreakpoint(BreakpointModelId id) const
case BreakpointAtFork: case BreakpointAtFork:
case WatchpointAtExpression: case WatchpointAtExpression:
case BreakpointAtSysCall: case BreakpointAtSysCall:
case BreakpointOnSignalHandler:
return false; return false;
case WatchpointAtAddress: case WatchpointAtAddress:
case BreakpointByFileAndLine: case BreakpointByFileAndLine:

View File

@@ -107,6 +107,7 @@ static BreakpointParameters fixWinMSVCBreakpoint(const BreakpointParameters &p)
case WatchpointAtExpression: case WatchpointAtExpression:
case BreakpointAtSysCall: case BreakpointAtSysCall:
case WatchpointAtAddress: case WatchpointAtAddress:
case BreakpointOnSignalHandler:
break; break;
case BreakpointAtExec: { // Emulate by breaking on CreateProcessW(). case BreakpointAtExec: { // Emulate by breaking on CreateProcessW().
BreakpointParameters rc(BreakpointByFunction); BreakpointParameters rc(BreakpointByFunction);
@@ -163,6 +164,7 @@ QByteArray cdbAddBreakpointCommand(const BreakpointParameters &bpIn,
case BreakpointAtCatch: case BreakpointAtCatch:
case BreakpointAtThrow: case BreakpointAtThrow:
case BreakpointAtMain: case BreakpointAtMain:
case BreakpointOnSignalHandler:
QTC_ASSERT(false, return QByteArray(); ) QTC_ASSERT(false, return QByteArray(); )
break; break;
case BreakpointByAddress: case BreakpointByAddress:

View File

@@ -30,6 +30,7 @@
** **
**************************************************************************/ **************************************************************************/
#include "qmldebuggerclient.h" #include "qmldebuggerclient.h"
#include "breakpoint.h"
#include <extensionsystem/pluginmanager.h> #include <extensionsystem/pluginmanager.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
@@ -54,6 +55,11 @@ QmlDebuggerClient::~QmlDebuggerClient()
delete d; delete d;
} }
bool QmlDebuggerClient::acceptsBreakpoint(const BreakpointModelId &/*id*/)
{
return false;
}
void QmlDebuggerClient::statusChanged(Status status) void QmlDebuggerClient::statusChanged(Status status)
{ {
emit newStatus(status); emit newStatus(status);

View File

@@ -65,13 +65,14 @@ public:
virtual void activateFrame(int index) = 0; virtual void activateFrame(int index) = 0;
virtual void insertBreakpoint(BreakpointModelId id) = 0; virtual bool acceptsBreakpoint(const BreakpointModelId &id);
virtual void removeBreakpoint(BreakpointModelId id) = 0; virtual void insertBreakpoint(const BreakpointModelId &id) = 0;
virtual void changeBreakpoint(BreakpointModelId id) = 0; virtual void removeBreakpoint(const BreakpointModelId &id) = 0;
virtual void changeBreakpoint(const BreakpointModelId &id) = 0;
virtual void updateBreakpoints() = 0; virtual void updateBreakpoints() = 0;
virtual void assignValueInDebugger(const QByteArray expr, const quint64 &id, virtual void assignValueInDebugger(const QByteArray expr, const quint64 &id,
const QString &property, const QString value) = 0; const QString &property, const QString &value) = 0;
virtual void updateWatchData(const WatchData *data) = 0; virtual void updateWatchData(const WatchData *data) = 0;
virtual void executeDebuggerCommand(const QString &command) = 0; virtual void executeDebuggerCommand(const QString &command) = 0;

View File

@@ -603,7 +603,18 @@ void QmlEngine::attemptBreakpointSynchronization()
bool QmlEngine::acceptsBreakpoint(BreakpointModelId id) const bool QmlEngine::acceptsBreakpoint(BreakpointModelId id) const
{ {
return !DebuggerEngine::isCppBreakpoint(breakHandler()->breakpointData(id)); if (!DebuggerEngine::isCppBreakpoint(breakHandler()->breakpointData(id)))
return true;
//If it is a Cpp Breakpoint query if the type can be also handled by the debugger client
//TODO: enable setting of breakpoints before start of debug session
//For now, the event breakpoint can be set after the activeDebuggerClient is known
//This is because the older client does not support BreakpointOnSignalHandler
bool acceptBreakpoint = false;
if (d->m_adapter.activeDebuggerClient()) {
acceptBreakpoint = d->m_adapter.activeDebuggerClient()->acceptsBreakpoint(id);
}
return acceptBreakpoint;
} }
void QmlEngine::loadSymbols(const QString &moduleName) void QmlEngine::loadSymbols(const QString &moduleName)

View File

@@ -312,7 +312,13 @@ void QmlV8DebuggerClient::activateFrame(int index)
setLocals(index); setLocals(index);
} }
void QmlV8DebuggerClient::insertBreakpoint(BreakpointModelId id) bool QmlV8DebuggerClient::acceptsBreakpoint(const BreakpointModelId &id)
{
BreakpointType type = d->engine->breakHandler()->breakpointData(id).type;
return ((type == BreakpointOnSignalHandler) || (type == BreakpointByFunction));
}
void QmlV8DebuggerClient::insertBreakpoint(const BreakpointModelId &id)
{ {
BreakHandler *handler = d->engine->breakHandler(); BreakHandler *handler = d->engine->breakHandler();
QByteArray request; QByteArray request;
@@ -327,6 +333,9 @@ void QmlV8DebuggerClient::insertBreakpoint(BreakpointModelId id)
} else if (handler->breakpointData(id).type == BreakpointByFunction) { } else if (handler->breakpointData(id).type == BreakpointByFunction) {
JsonInputStream(request) << "type" << ':' << "function"; JsonInputStream(request) << "type" << ':' << "function";
JsonInputStream(request) << ',' << "target" << ':' << handler->functionName(id).toUtf8(); JsonInputStream(request) << ',' << "target" << ':' << handler->functionName(id).toUtf8();
} else if (handler->breakpointData(id).type == BreakpointOnSignalHandler) {
JsonInputStream(request) << "type" << ':' << "event";
JsonInputStream(request) << ',' << "target" << ':' << handler->functionName(id).toUtf8();
} }
JsonInputStream(request) << '}'; JsonInputStream(request) << '}';
JsonInputStream(request) << '}'; JsonInputStream(request) << '}';
@@ -335,7 +344,7 @@ void QmlV8DebuggerClient::insertBreakpoint(BreakpointModelId id)
sendMessage(packMessage(request)); sendMessage(packMessage(request));
} }
void QmlV8DebuggerClient::removeBreakpoint(BreakpointModelId id) void QmlV8DebuggerClient::removeBreakpoint(const BreakpointModelId &id)
{ {
int breakpoint = d->breakpoints.value(id); int breakpoint = d->breakpoints.value(id);
d->breakpoints.remove(id); d->breakpoints.remove(id);
@@ -354,7 +363,7 @@ void QmlV8DebuggerClient::removeBreakpoint(BreakpointModelId id)
sendMessage(packMessage(request)); sendMessage(packMessage(request));
} }
void QmlV8DebuggerClient::changeBreakpoint(BreakpointModelId /*id*/) void QmlV8DebuggerClient::changeBreakpoint(const BreakpointModelId &/*id*/)
{ {
} }
@@ -363,7 +372,7 @@ void QmlV8DebuggerClient::updateBreakpoints()
} }
void QmlV8DebuggerClient::assignValueInDebugger(const QByteArray /*expr*/, const quint64 &/*id*/, void QmlV8DebuggerClient::assignValueInDebugger(const QByteArray /*expr*/, const quint64 &/*id*/,
const QString &/*property*/, const QString /*value*/) const QString &/*property*/, const QString &/*value*/)
{ {
//TODO:: //TODO::
} }
@@ -468,7 +477,7 @@ void QmlV8DebuggerClient::messageReceived(const QByteArray &data)
ds >> response; ds >> response;
JsonValue value(response); JsonValue value(response);
QString type = value.findChild("type").toVariant().toString(); const QString type = value.findChild("type").toVariant().toString();
if (type == "response") { if (type == "response") {
@@ -478,7 +487,7 @@ void QmlV8DebuggerClient::messageReceived(const QByteArray &data)
return; return;
} }
QString debugCommand(value.findChild("command").toVariant().toString()); const QString debugCommand(value.findChild("command").toVariant().toString());
if (debugCommand == "backtrace") { if (debugCommand == "backtrace") {
setStackFrames(response); setStackFrames(response);
@@ -491,6 +500,12 @@ void QmlV8DebuggerClient::messageReceived(const QByteArray &data)
BreakpointModelId id = d->breakpointsSync.take(sequence); BreakpointModelId id = d->breakpointsSync.take(sequence);
d->breakpoints.insert(id,breakpoint); d->breakpoints.insert(id,breakpoint);
//If this is an event breakpoint then set state = BreakpointInsertOk
const QString breakpointType = value.findChild("body").findChild("type").toVariant().toString();
if (breakpointType == "event") {
d->engine->breakHandler()->notifyBreakpointInsertOk(id);
}
} else if (debugCommand == "evaluate") { } else if (debugCommand == "evaluate") {
setExpression(response); setExpression(response);
@@ -504,7 +519,7 @@ void QmlV8DebuggerClient::messageReceived(const QByteArray &data)
} }
} else if (type == "event") { } else if (type == "event") {
QString event(value.findChild("event").toVariant().toString()); const QString event(value.findChild("event").toVariant().toString());
if (event == "break") { if (event == "break") {
d->engine->inferiorSpontaneousStop(); d->engine->inferiorSpontaneousStop();

View File

@@ -80,13 +80,14 @@ public:
void activateFrame(int index); void activateFrame(int index);
void insertBreakpoint(BreakpointModelId id); bool acceptsBreakpoint(const BreakpointModelId &id);
void removeBreakpoint(BreakpointModelId id); void insertBreakpoint(const BreakpointModelId &id);
void changeBreakpoint(BreakpointModelId id); void removeBreakpoint(const BreakpointModelId &id);
void changeBreakpoint(const BreakpointModelId &id);
void updateBreakpoints(); void updateBreakpoints();
void assignValueInDebugger(const QByteArray expr, const quint64 &id, void assignValueInDebugger(const QByteArray expr, const quint64 &id,
const QString &property, const QString value); const QString &property, const QString &value);
void updateWatchData(const WatchData *data); void updateWatchData(const WatchData *data);
void executeDebuggerCommand(const QString &command); void executeDebuggerCommand(const QString &command);

View File

@@ -216,7 +216,7 @@ void QScriptDebuggerClient::activateFrame(int index)
sendMessage(reply); sendMessage(reply);
} }
void QScriptDebuggerClient::insertBreakpoint(BreakpointModelId id) void QScriptDebuggerClient::insertBreakpoint(const BreakpointModelId &id)
{ {
BreakHandler *handler = d->engine->breakHandler(); BreakHandler *handler = d->engine->breakHandler();
JSAgentBreakpointData bp; JSAgentBreakpointData bp;
@@ -226,7 +226,7 @@ void QScriptDebuggerClient::insertBreakpoint(BreakpointModelId id)
d->breakpoints.insert(bp); d->breakpoints.insert(bp);
} }
void QScriptDebuggerClient::removeBreakpoint(BreakpointModelId id) void QScriptDebuggerClient::removeBreakpoint(const BreakpointModelId &id)
{ {
BreakHandler *handler = d->engine->breakHandler(); BreakHandler *handler = d->engine->breakHandler();
JSAgentBreakpointData bp; JSAgentBreakpointData bp;
@@ -236,7 +236,7 @@ void QScriptDebuggerClient::removeBreakpoint(BreakpointModelId id)
d->breakpoints.remove(bp); d->breakpoints.remove(bp);
} }
void QScriptDebuggerClient::changeBreakpoint(BreakpointModelId /*id*/) void QScriptDebuggerClient::changeBreakpoint(const BreakpointModelId &/*id*/)
{ {
} }
@@ -251,7 +251,7 @@ void QScriptDebuggerClient::updateBreakpoints()
} }
void QScriptDebuggerClient::assignValueInDebugger(const QByteArray expr, const quint64 &id, void QScriptDebuggerClient::assignValueInDebugger(const QByteArray expr, const quint64 &id,
const QString &property, const QString value) const QString &property, const QString &value)
{ {
QByteArray reply; QByteArray reply;
QDataStream rs(&reply, QIODevice::WriteOnly); QDataStream rs(&reply, QIODevice::WriteOnly);

View File

@@ -64,13 +64,13 @@ public:
void activateFrame(int index); void activateFrame(int index);
void insertBreakpoint(BreakpointModelId id); void insertBreakpoint(const BreakpointModelId &id);
void removeBreakpoint(BreakpointModelId id); void removeBreakpoint(const BreakpointModelId &id);
void changeBreakpoint(BreakpointModelId id); void changeBreakpoint(const BreakpointModelId &id);
void updateBreakpoints(); void updateBreakpoints();
void assignValueInDebugger(const QByteArray expr, const quint64 &id, void assignValueInDebugger(const QByteArray expr, const quint64 &id,
const QString &property, const QString value); const QString &property, const QString &value);
void updateWatchData(const WatchData *data); void updateWatchData(const WatchData *data);
void executeDebuggerCommand(const QString &command); void executeDebuggerCommand(const QString &command);