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

Last change on this file since 573 was 561, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.1 sources.

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