source: trunk/src/scripttools/debugging/qscriptdebuggeragent.cpp@ 5

Last change on this file since 5 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 22.3 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the QtSCriptTools module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you are unsure which license is appropriate for your use, please
37** contact the sales department at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qscriptdebuggeragent_p.h"
43#include "qscriptdebuggeragent_p_p.h"
44#include "qscriptdebuggerbackend_p_p.h"
45
46#include <QtCore/qcoreapplication.h>
47#include <QtCore/qset.h>
48#include <QtScript/qscriptengine.h>
49
50QT_BEGIN_NAMESPACE
51
52/*!
53 \since 4.5
54 \class QScriptDebuggerAgent
55 \internal
56
57 This class implements a state machine that uses the low-level events
58 reported by the QScriptEngineAgent interface to implement debugging-
59 specific functionality such as stepping and breakpoints. It is used
60 internally by the QScriptDebuggerBackend class.
61*/
62
63QScriptDebuggerAgentPrivate::QScriptDebuggerAgentPrivate()
64{
65 state = NoState;
66 nextBreakpointId = 1;
67 nextContextId = 0;
68 statementCounter = 0;
69}
70
71QScriptDebuggerAgentPrivate::~QScriptDebuggerAgentPrivate()
72{
73}
74
75QScriptDebuggerAgentPrivate *QScriptDebuggerAgentPrivate::get(
76 QScriptDebuggerAgent *q)
77{
78 if (!q)
79 return 0;
80 return q->d_func();
81}
82
83
84/*!
85 Constructs a new agent for the given \a engine. The agent will
86 report debugging-related events (e.g. step completion) to the given
87 \a backend.
88*/
89QScriptDebuggerAgent::QScriptDebuggerAgent(
90 QScriptDebuggerBackendPrivate *backend, QScriptEngine *engine)
91#if QT_VERSION >= 0x040500
92 : QScriptEngineAgent(*new QScriptDebuggerAgentPrivate, engine)
93#else
94 : QScriptEngineAgent(engine), d_ptr(new QScriptDebuggerAgentPrivate)
95#endif
96{
97 Q_D(QScriptDebuggerAgent);
98#if QT_VERSION < 0x040500
99 d_ptr->q_ptr = this;
100#endif
101 d->backend = backend;
102
103 QScriptContext *ctx = engine->currentContext();
104 while (ctx) {
105 d->scriptIdStack.append(QList<qint64>());
106 d->contextIdStack.append(d->nextContextId);
107 ++d->nextContextId;
108 ctx = ctx->parentContext();
109 }
110}
111
112/*!
113 Destroys this QScriptDebuggerAgent.
114*/
115QScriptDebuggerAgent::~QScriptDebuggerAgent()
116{
117 Q_D(QScriptDebuggerAgent);
118 if (d->backend)
119 d->backend->agentDestroyed(this);
120#if QT_VERSION < 0x040500
121 delete d_ptr;
122#endif
123}
124
125/*!
126 Instructs the agent to perform a "step into" operation. This
127 function returns immediately. The agent will report step completion
128 at a later time, i.e. when script statements are evaluted.
129*/
130void QScriptDebuggerAgent::enterStepIntoMode(int count)
131{
132 Q_D(QScriptDebuggerAgent);
133 d->state = QScriptDebuggerAgentPrivate::SteppingIntoState;
134 d->stepCount = count;
135 d->stepResult = QScriptValue();
136}
137
138/*!
139 Instructs the agent to perform a "step over" operation. This
140 function returns immediately. The agent will report step completion
141 at a later time, i.e. when script statements are evaluted.
142*/
143void QScriptDebuggerAgent::enterStepOverMode(int count)
144{
145 Q_D(QScriptDebuggerAgent);
146 d->state = QScriptDebuggerAgentPrivate::SteppingOverState;
147 if (engine()->isEvaluating())
148 d->stepDepth = 0;
149 else
150 d->stepDepth = -1;
151 d->stepCount = count;
152 d->stepResult = QScriptValue();
153}
154
155/*!
156 Instructs the agent to perform a "step out" operation. This
157 function returns immediately. The agent will report step completion
158 at a later time, i.e. when script statements are evaluted.
159*/
160void QScriptDebuggerAgent::enterStepOutMode()
161{
162 Q_D(QScriptDebuggerAgent);
163 d->state = QScriptDebuggerAgentPrivate::SteppingOutState;
164 if (engine()->isEvaluating())
165 d->stepDepth = 0;
166 else
167 d->stepDepth = -1;
168}
169
170/*!
171 Instructs the agent to continue evaluation.
172 This function returns immediately.
173*/
174void QScriptDebuggerAgent::enterContinueMode()
175{
176 Q_D(QScriptDebuggerAgent);
177 d->state = QScriptDebuggerAgentPrivate::NoState;
178}
179
180/*!
181 Instructs the agent to interrupt evaluation.
182 This function returns immediately.
183*/
184void QScriptDebuggerAgent::enterInterruptMode()
185{
186 Q_D(QScriptDebuggerAgent);
187 d->state = QScriptDebuggerAgentPrivate::InterruptingState;
188}
189
190/*!
191 Instructs the agent to continue evaluation until the location
192 described by \a fileName and \a lineNumber is reached. This
193 function returns immediately.
194*/
195void QScriptDebuggerAgent::enterRunToLocationMode(const QString &fileName, int lineNumber)
196{
197 Q_D(QScriptDebuggerAgent);
198 d->targetFileName = fileName;
199 d->targetLineNumber = lineNumber;
200 d->targetScriptId = resolveScript(fileName);
201 d->state = QScriptDebuggerAgentPrivate::RunningToLocationState;
202}
203
204/*!
205 Instructs the agent to continue evaluation until the location
206 described by \a scriptId and \a lineNumber is reached. This
207 function returns immediately.
208*/
209void QScriptDebuggerAgent::enterRunToLocationMode(qint64 scriptId, int lineNumber)
210{
211 Q_D(QScriptDebuggerAgent);
212 d->targetScriptId = scriptId;
213 d->targetFileName = QString();
214 d->targetLineNumber = lineNumber;
215 d->state = QScriptDebuggerAgentPrivate::RunningToLocationState;
216}
217
218void QScriptDebuggerAgent::enterReturnByForceMode(int contextIndex, const QScriptValue &value)
219{
220 Q_D(QScriptDebuggerAgent);
221 d->returnCounter = contextIndex + 1;
222 d->returnValue = QScriptValue();
223 d->state = QScriptDebuggerAgentPrivate::ReturningByForceState;
224 // throw an exception; we will catch it when the proper frame is popped
225 engine()->currentContext()->throwValue(value);
226}
227
228/*!
229 Sets a breakpoint defined by the given \a data.
230 Returns an integer that uniquely identifies the new breakpoint,
231 or -1 if setting the breakpoint failed.
232*/
233int QScriptDebuggerAgent::setBreakpoint(const QScriptBreakpointData &data)
234{
235 Q_D(QScriptDebuggerAgent);
236 qint64 scriptId = data.scriptId();
237 if (scriptId != -1) {
238 if (!d->scripts.contains(scriptId)) {
239 // that script has been unloaded, so invalidate the ID
240 scriptId = -1;
241 const_cast<QScriptBreakpointData&>(data).setScriptId(-1);
242 } else if (data.fileName().isEmpty()) {
243 QString fileName = d->scripts[scriptId].fileName();
244 const_cast<QScriptBreakpointData&>(data).setFileName(fileName);
245 }
246 }
247
248 int id = d->nextBreakpointId;
249 ++d->nextBreakpointId;
250
251 if (scriptId != -1) {
252 d->resolvedBreakpoints[scriptId].append(id);
253 } else {
254 QString fileName = data.fileName();
255 bool resolved = false;
256 QScriptScriptMap::const_iterator it;
257 for (it = d->scripts.constBegin(); it != d->scripts.constEnd(); ++it) {
258 if (it.value().fileName() == fileName) {
259 d->resolvedBreakpoints[it.key()].append(id);
260 resolved = true;
261 break;
262 }
263 }
264 if (!resolved)
265 d->unresolvedBreakpoints[fileName].append(id);
266 }
267
268 d->breakpoints.insert(id, data);
269
270 return id;
271}
272
273/*!
274 Deletes the breakpoint with the given \a id.
275 Returns true if the breakpoint was deleted, false if
276 no such breakpoint exists.
277*/
278bool QScriptDebuggerAgent::deleteBreakpoint(int id)
279{
280 Q_D(QScriptDebuggerAgent);
281 if (!d->breakpoints.contains(id))
282 return false;
283 d->breakpoints.remove(id);
284 bool found = false;
285 {
286 QHash<qint64, QList<int> >::iterator it;
287 it = d->resolvedBreakpoints.begin();
288 for ( ; !found && (it != d->resolvedBreakpoints.end()); ) {
289 QList<int> &lst = it.value();
290 Q_ASSERT(!lst.isEmpty());
291 for (int i = 0; i < lst.size(); ++i) {
292 if (lst.at(i) == id) {
293 lst.removeAt(i);
294 found = true;
295 break;
296 }
297 }
298 if (lst.isEmpty())
299 it = d->resolvedBreakpoints.erase(it);
300 else
301 ++it;
302 }
303 }
304 if (!found) {
305 QHash<QString, QList<int> >::iterator it;
306 it = d->unresolvedBreakpoints.begin();
307 for ( ; !found && (it != d->unresolvedBreakpoints.end()); ) {
308 QList<int> &lst = it.value();
309 Q_ASSERT(!lst.isEmpty());
310 for (int i = 0; i < lst.size(); ++i) {
311 if (lst.at(i) == id) {
312 lst.removeAt(i);
313 found = true;
314 break;
315 }
316 }
317 if (lst.isEmpty())
318 it = d->unresolvedBreakpoints.erase(it);
319 else
320 ++it;
321 }
322 }
323 return found;
324}
325
326/*!
327 Deletes all breakpoints.
328*/
329void QScriptDebuggerAgent::deleteAllBreakpoints()
330{
331 Q_D(QScriptDebuggerAgent);
332 d->breakpoints.clear();
333 d->resolvedBreakpoints.clear();
334 d->unresolvedBreakpoints.clear();
335}
336
337/*!
338 Returns the data associated with the breakpoint with the given \a
339 id.
340*/
341QScriptBreakpointData QScriptDebuggerAgent::breakpointData(int id) const
342{
343 Q_D(const QScriptDebuggerAgent);
344 return d->breakpoints.value(id);
345}
346
347/*!
348 Sets the data associated with the breakpoint with the given \a
349 id.
350*/
351bool QScriptDebuggerAgent::setBreakpointData(int id,
352 const QScriptBreakpointData &data)
353{
354 Q_D(QScriptDebuggerAgent);
355 if (!d->breakpoints.contains(id))
356 return false;
357 d->breakpoints[id] = data;
358 return true;
359}
360
361/*!
362 Returns all breakpoints.
363*/
364QScriptBreakpointMap QScriptDebuggerAgent::breakpoints() const
365{
366 Q_D(const QScriptDebuggerAgent);
367 return d->breakpoints;
368}
369
370/*!
371 Returns all scripts.
372*/
373QScriptScriptMap QScriptDebuggerAgent::scripts() const
374{
375 Q_D(const QScriptDebuggerAgent);
376 return d->scripts;
377}
378
379/*!
380 Returns the data associated with the script with the given \a id.
381*/
382QScriptScriptData QScriptDebuggerAgent::scriptData(qint64 id) const
383{
384 Q_D(const QScriptDebuggerAgent);
385 return d->scripts.value(id);
386}
387
388/*!
389 Checkpoints the current scripts.
390*/
391void QScriptDebuggerAgent::scriptsCheckpoint()
392{
393 Q_D(QScriptDebuggerAgent);
394 d->previousCheckpointScripts = d->checkpointScripts;
395 d->checkpointScripts = d->scripts;
396}
397
398/*!
399 Returns the difference between the current checkpoint and the
400 previous checkpoint. The first item in the pair is a list containing
401 the identifiers of the scripts that were added. The second item in
402 the pair is a list containing the identifiers of the scripts that
403 were removed.
404*/
405QPair<QList<qint64>, QList<qint64> > QScriptDebuggerAgent::scriptsDelta() const
406{
407 Q_D(const QScriptDebuggerAgent);
408 QSet<qint64> prevSet = d->previousCheckpointScripts.keys().toSet();
409 QSet<qint64> currSet = d->checkpointScripts.keys().toSet();
410 QSet<qint64> addedScriptIds = currSet - prevSet;
411 QSet<qint64> removedScriptIds = prevSet - currSet;
412 return qMakePair(addedScriptIds.toList(), removedScriptIds.toList());
413}
414
415/*!
416 Returns the identifier of the script that has the given \a fileName,
417 or -1 if there is no such script.
418*/
419qint64 QScriptDebuggerAgent::resolveScript(const QString &fileName) const
420{
421 Q_D(const QScriptDebuggerAgent);
422 QScriptScriptMap::const_iterator it;
423 for (it = d->scripts.constBegin(); it != d->scripts.constEnd(); ++it) {
424 if (it.value().fileName() == fileName)
425 return it.key();
426 }
427 return -1;
428}
429
430QList<qint64> QScriptDebuggerAgent::contextIds() const
431{
432 Q_D(const QScriptDebuggerAgent);
433 return d->contextIdStack;
434}
435
436QPair<QList<qint64>, QList<qint64> > QScriptDebuggerAgent::contextsCheckpoint()
437{
438 Q_D(QScriptDebuggerAgent);
439 int i = d->checkpointContextIdStack.size() - 1;
440 int j = d->contextIdStack.size() - 1;
441 for ( ; (i >= 0) && (j >= 0); --i, --j) {
442 if (d->checkpointContextIdStack.at(i) != d->contextIdStack.at(j))
443 break;
444 }
445 QList<qint64> removed = d->checkpointContextIdStack.mid(0, i+1);
446 QList<qint64> added = d->contextIdStack.mid(0, j+1);
447 d->checkpointContextIdStack = d->contextIdStack;
448 return qMakePair(removed, added);
449}
450
451void QScriptDebuggerAgent::nullifyBackendPointer()
452{
453 Q_D(QScriptDebuggerAgent);
454 d->backend = 0;
455}
456
457/*!
458 \reimp
459*/
460void QScriptDebuggerAgent::scriptLoad(qint64 id, const QString &program,
461 const QString &fileName, int baseLineNumber)
462{
463 Q_D(QScriptDebuggerAgent);
464 QScriptScriptData data = QScriptScriptData(program, fileName, baseLineNumber);
465 d->scripts.insert(id, data);
466
467 if ((d->state == QScriptDebuggerAgentPrivate::RunningToLocationState)
468 && (d->targetScriptId == -1)
469 && ((d->targetFileName == fileName) || d->targetFileName.isEmpty())) {
470 d->targetScriptId = id;
471 }
472
473 if (!fileName.isEmpty()) {
474 QList<int> lst = d->unresolvedBreakpoints.take(fileName);
475 if (!lst.isEmpty())
476 d->resolvedBreakpoints.insert(id, lst);
477 }
478}
479
480/*!
481 \reimp
482*/
483void QScriptDebuggerAgent::scriptUnload(qint64 id)
484{
485 Q_D(QScriptDebuggerAgent);
486 QScriptScriptData data = d->scripts.take(id);
487 QString fileName = data.fileName();
488
489 if ((d->state == QScriptDebuggerAgentPrivate::RunningToLocationState)
490 && (d->targetScriptId == id)) {
491 d->targetScriptId = -1;
492 d->targetFileName = fileName;
493 }
494
495 if (!fileName.isEmpty()) {
496 QList<int> lst = d->resolvedBreakpoints.take(id);
497 if (!lst.isEmpty())
498 d->unresolvedBreakpoints.insert(fileName, lst);
499 }
500}
501
502/*!
503 \reimp
504*/
505void QScriptDebuggerAgent::contextPush()
506{
507 Q_D(QScriptDebuggerAgent);
508 d->scriptIdStack.append(QList<qint64>());
509 d->contextIdStack.prepend(d->nextContextId);
510 ++d->nextContextId;
511}
512
513/*!
514 \reimp
515*/
516void QScriptDebuggerAgent::contextPop()
517{
518 Q_D(QScriptDebuggerAgent);
519 d->scriptIdStack.removeLast();
520 d->contextIdStack.removeFirst();
521}
522
523/*!
524 \reimp
525*/
526void QScriptDebuggerAgent::functionEntry(qint64 scriptId)
527{
528 Q_D(QScriptDebuggerAgent);
529 QList<qint64> &ids = d->scriptIdStack.last();
530 ids.append(scriptId);
531 if ((d->state == QScriptDebuggerAgentPrivate::SteppingOverState)
532 || (d->state == QScriptDebuggerAgentPrivate::SteppingOutState)) {
533 ++d->stepDepth;
534 }
535}
536
537/*!
538 \reimp
539*/
540void QScriptDebuggerAgent::functionExit(qint64 scriptId,
541 const QScriptValue &returnValue)
542{
543 Q_UNUSED(scriptId);
544 Q_D(QScriptDebuggerAgent);
545 QList<qint64> &ids = d->scriptIdStack.last();
546 ids.removeLast();
547 if (d->state == QScriptDebuggerAgentPrivate::SteppingOverState) {
548 --d->stepDepth;
549 } else if (d->state == QScriptDebuggerAgentPrivate::SteppingOutState) {
550 if (--d->stepDepth < 0) {
551 d->stepResult = returnValue;
552 d->state = QScriptDebuggerAgentPrivate::SteppedOutState;
553 }
554 } else if (d->state == QScriptDebuggerAgentPrivate::ReturningByForceState) {
555 if (--d->returnCounter == 0) {
556 d->returnValue = returnValue;
557 d->state = QScriptDebuggerAgentPrivate::ReturnedByForceState;
558 engine()->clearExceptions();
559 }
560 }
561}
562
563/*!
564 \reimp
565*/
566void QScriptDebuggerAgent::positionChange(qint64 scriptId,
567 int lineNumber, int columnNumber)
568{
569 Q_D(QScriptDebuggerAgent);
570 if (engine()->processEventsInterval() == -1) {
571 // see if it's time to call processEvents()
572 if ((++d->statementCounter % 25000) == 0) {
573 if (!d->processEventsTimer.isNull()) {
574 if (d->processEventsTimer.elapsed() > 30) {
575 QCoreApplication::processEvents();
576 d->processEventsTimer.restart();
577 }
578 } else {
579 d->processEventsTimer.start();
580 }
581 }
582 }
583
584 // check breakpoints
585 {
586 QList<int> lst = d->resolvedBreakpoints.value(scriptId);
587 for (int i = 0; i < lst.size(); ++i) {
588 int id = lst.at(i);
589 QScriptBreakpointData &data = d->breakpoints[id];
590 if (!data.isEnabled())
591 continue;
592 if (data.lineNumber() != lineNumber)
593 continue;
594 if (!data.condition().isEmpty()) {
595 // ### careful, evaluate() can cause an exception
596 // ### disable callbacks in nested evaluate?
597 QScriptDebuggerAgentPrivate::State was = d->state;
598 d->state = QScriptDebuggerAgentPrivate::NoState;
599 QScriptValue ret = engine()->evaluate(
600 data.condition(),
601 QString::fromLatin1("Breakpoint %0 condition checker").arg(id));
602 if (!ret.isError())
603 d->state = was;
604 if (!ret.toBoolean())
605 continue;
606 }
607 if (!data.hit())
608 continue;
609 d->hitBreakpointId = id;
610 d->state = QScriptDebuggerAgentPrivate::BreakpointState;
611 }
612 }
613
614 switch (d->state) {
615 case QScriptDebuggerAgentPrivate::NoState:
616 case QScriptDebuggerAgentPrivate::SteppingOutState:
617 case QScriptDebuggerAgentPrivate::ReturningByForceState:
618 // Do nothing
619 break;
620
621 case QScriptDebuggerAgentPrivate::SteppingIntoState:
622 if (--d->stepCount == 0) {
623 d->state = QScriptDebuggerAgentPrivate::NoState;
624 if (d->backend)
625 d->backend->stepped(scriptId, lineNumber, columnNumber, QScriptValue());
626 }
627 break;
628
629 case QScriptDebuggerAgentPrivate::SteppingOverState:
630 if ((d->stepDepth > 0) || (--d->stepCount != 0))
631 break;
632 // fallthrough
633 case QScriptDebuggerAgentPrivate::SteppedOverState:
634 d->state = QScriptDebuggerAgentPrivate::NoState;
635 if (d->backend)
636 d->backend->stepped(scriptId, lineNumber, columnNumber, d->stepResult);
637 break;
638
639 case QScriptDebuggerAgentPrivate::SteppedOutState:
640 d->state = QScriptDebuggerAgentPrivate::NoState;
641 if (d->backend)
642 d->backend->stepped(scriptId, lineNumber, columnNumber, d->stepResult);
643 break;
644
645 case QScriptDebuggerAgentPrivate::RunningToLocationState:
646 if (((lineNumber == d->targetLineNumber) || (d->targetLineNumber == -1))
647 && (scriptId == d->targetScriptId)) {
648 d->state = QScriptDebuggerAgentPrivate::NoState;
649 if (d->backend)
650 d->backend->locationReached(scriptId, lineNumber, columnNumber);
651 }
652 break;
653
654 case QScriptDebuggerAgentPrivate::InterruptingState:
655 d->state = QScriptDebuggerAgentPrivate::NoState;
656 if (d->backend)
657 d->backend->interrupted(scriptId, lineNumber, columnNumber);
658 break;
659
660 case QScriptDebuggerAgentPrivate::BreakpointState:
661 d->state = QScriptDebuggerAgentPrivate::NoState;
662 if (d->backend)
663 d->backend->breakpoint(scriptId, lineNumber, columnNumber, d->hitBreakpointId);
664 if (d->breakpoints.value(d->hitBreakpointId).isSingleShot())
665 deleteBreakpoint(d->hitBreakpointId);
666 break;
667
668 case QScriptDebuggerAgentPrivate::ReturnedByForceState:
669 d->state = QScriptDebuggerAgentPrivate::NoState;
670 if (d->backend)
671 d->backend->forcedReturn(scriptId, lineNumber, columnNumber, d->returnValue);
672 break;
673
674 case QScriptDebuggerAgentPrivate::SteppedIntoState:
675 case QScriptDebuggerAgentPrivate::ReachedLocationState:
676 case QScriptDebuggerAgentPrivate::InterruptedState:
677// ### deal with the case when code is evaluated while we're already paused
678// Q_ASSERT(false);
679 break;
680 }
681}
682
683/*!
684 \reimp
685*/
686void QScriptDebuggerAgent::exceptionThrow(qint64 scriptId,
687 const QScriptValue &exception,
688 bool hasHandler)
689{
690 Q_D(QScriptDebuggerAgent);
691 if (d->state == QScriptDebuggerAgentPrivate::ReturningByForceState) {
692 // we threw this exception ourselves, so ignore it for now
693 // (see functionExit()).
694 return;
695 }
696 if (d->backend)
697 d->backend->exception(scriptId, exception, hasHandler);
698}
699
700/*!
701 \reimp
702*/
703void QScriptDebuggerAgent::exceptionCatch(qint64 scriptId,
704 const QScriptValue &exception)
705{
706 Q_UNUSED(scriptId);
707 Q_UNUSED(exception);
708}
709
710/*!
711 \reimp
712*/
713bool QScriptDebuggerAgent::supportsExtension(Extension extension) const
714{
715#if QT_VERSION >= 0x040500
716 return (extension == DebuggerInvocationRequest);
717#else
718 Q_UNUSED(extension);
719 return false;
720#endif
721}
722
723/*!
724 \reimp
725*/
726QVariant QScriptDebuggerAgent::extension(Extension extension,
727 const QVariant &argument)
728{
729 Q_UNUSED(extension);
730#if QT_VERSION >= 0x040500
731 Q_D(QScriptDebuggerAgent);
732 Q_ASSERT(extension == DebuggerInvocationRequest);
733 QVariantList lst = argument.toList();
734 qint64 scriptId = lst.at(0).toLongLong();
735 int lineNumber = lst.at(1).toInt();
736 int columnNumber = lst.at(2).toInt();
737 d->state = QScriptDebuggerAgentPrivate::NoState;
738 if (d->backend) {
739 d->backend->debuggerInvocationRequest(
740 scriptId, lineNumber, columnNumber);
741 }
742#else
743 Q_UNUSED(argument);
744#endif
745 return QVariant();
746}
747
748QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.