Qt 4.8
qscriptdebuggercommandexecutor.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtSCriptTools module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
43 
47 #include "qscriptdebuggervalue_p.h"
52 
53 #include <QtCore/qstringlist.h>
54 #include <QtScript/qscriptengine.h>
55 #include <QtScript/qscriptcontextinfo.h>
56 #include <QtScript/qscriptvalueiterator.h>
57 #include <QtCore/qdebug.h>
58 
63 
65 
83 {
84 public:
87 };
88 
90 {
91 }
92 
94 {
95 }
96 
99 {
100 }
101 
103 {
104 }
105 
106 static bool isPrefixOf(const QString &prefix, const QString &what)
107 {
108  return ((what.length() > prefix.length())
109  && what.startsWith(prefix));
110 }
111 
116  QScriptDebuggerBackend *backend,
117  const QScriptDebuggerCommand &command)
118 {
119  QScriptDebuggerResponse response;
120  switch (command.type()) {
122  break;
123 
125  backend->interruptEvaluation();
126  break;
127 
129  if (backend->engine()->isEvaluating()) {
130  backend->continueEvalution();
131  response.setAsync(true);
132  }
133  break;
134 
137  int count = attr.isValid() ? attr.toInt() : 1;
138  backend->stepInto(count);
139  response.setAsync(true);
140  } break;
141 
144  int count = attr.isValid() ? attr.toInt() : 1;
145  backend->stepOver(count);
146  response.setAsync(true);
147  } break;
148 
150  backend->stepOut();
151  response.setAsync(true);
152  break;
153 
155  backend->runToLocation(command.fileName(), command.lineNumber());
156  response.setAsync(true);
157  break;
158 
160  backend->runToLocation(command.scriptId(), command.lineNumber());
161  response.setAsync(true);
162  break;
163 
165  int contextIndex = command.contextIndex();
166  QScriptDebuggerValue value = command.scriptValue();
167  QScriptEngine *engine = backend->engine();
168  QScriptValue realValue = value.toScriptValue(engine);
169  backend->returnToCaller(contextIndex, realValue);
170  response.setAsync(true);
171  } break;
172 
174  backend->resume();
175  response.setAsync(true);
176  break;
177 
180  if (!data.isValid())
181  data = QScriptBreakpointData(command.fileName(), command.lineNumber());
182  int id = backend->setBreakpoint(data);
183  response.setResult(id);
184  } break;
185 
187  int id = command.breakpointId();
188  if (!backend->deleteBreakpoint(id))
190  } break;
191 
193  backend->deleteAllBreakpoints();
194  break;
195 
197  QScriptBreakpointMap bps = backend->breakpoints();
198  if (!bps.isEmpty())
199  response.setResult(bps);
200  } break;
201 
203  int id = command.breakpointId();
205  if (data.isValid())
206  response.setResult(data);
207  else
209  } break;
210 
212  int id = command.breakpointId();
214  if (!backend->setBreakpointData(id, data))
216  } break;
217 
219  QScriptScriptMap scripts = backend->scripts();
220  if (!scripts.isEmpty())
221  response.setResult(scripts);
222  } break;
223 
225  qint64 id = command.scriptId();
226  QScriptScriptData data = backend->scriptData(id);
227  if (data.isValid())
228  response.setResult(data);
229  else
231  } break;
232 
234  backend->scriptsCheckpoint();
235  response.setResult(QVariant::fromValue(backend->scriptsDelta()));
236  break;
237 
239  response.setResult(QVariant::fromValue(backend->scriptsDelta()));
240  break;
241 
243  response.setResult(backend->resolveScript(command.fileName()));
244  break;
245 
247  response.setResult(backend->backtrace());
248  break;
249 
251  response.setResult(backend->contextCount());
252  break;
253 
255  QScriptContext *ctx = backend->context(command.contextIndex());
256  if (ctx)
257  response.setResult(static_cast<int>(ctx->state()));
258  else
260  } break;
261 
263  int idx = command.contextIndex();
264  if ((idx >= 0) && (idx < backend->contextCount()))
265  response.setResult(backend->contextIds()[idx]);
266  else
268  } break;
269 
271  QScriptContext *ctx = backend->context(command.contextIndex());
272  if (ctx)
273  response.setResult(QScriptContextInfo(ctx));
274  else
276  } break;
277 
279  QScriptContext *ctx = backend->context(command.contextIndex());
280  if (ctx)
281  response.setResult(ctx->thisObject());
282  else
284  } break;
285 
287  QScriptContext *ctx = backend->context(command.contextIndex());
288  if (ctx)
289  response.setResult(ctx->activationObject());
290  else
292  } break;
293 
295  QScriptContext *ctx = backend->context(command.contextIndex());
296  if (ctx) {
298  QScriptValueList src = ctx->scopeChain();
299  for (int i = 0; i < src.size(); ++i)
300  dest.append(src.at(i));
301  response.setResult(dest);
302  } else {
304  }
305  } break;
306 
308  response.setResult(QVariant::fromValue(backend->contextsCheckpoint()));
309  } break;
310 
312  QScriptContext *ctx = backend->context(command.contextIndex());
313  int lineNumber = command.lineNumber();
315  QStringList path = attr.toStringList();
316  if (!ctx || path.isEmpty())
317  break;
318  QScriptContextInfo ctxInfo(ctx);
319  if (ctx->callee().isValid()
320  && ((lineNumber < ctxInfo.functionStartLineNumber())
321  || (lineNumber > ctxInfo.functionEndLineNumber()))) {
322  break;
323  }
324  QScriptValueList objects;
325  int pathIndex = 0;
326  if (path.at(0) == QLatin1String("this")) {
327  objects.append(ctx->thisObject());
328  ++pathIndex;
329  } else {
330  objects << ctx->scopeChain();
331  }
332  for (int i = 0; i < objects.size(); ++i) {
333  QScriptValue val = objects.at(i);
334  for (int j = pathIndex; val.isValid() && (j < path.size()); ++j) {
335  val = val.property(path.at(j));
336  }
337  if (val.isValid()) {
338  bool hadException = (ctx->state() == QScriptContext::ExceptionState);
339  QString str = val.toString();
340  if (!hadException && backend->engine()->hasUncaughtException())
341  backend->engine()->clearExceptions();
342  response.setResult(str);
343  break;
344  }
345  }
346  } break;
347 
349  QScriptContext *ctx = backend->context(command.contextIndex());
351  QStringList path = attr.toStringList();
352  if (!ctx || path.isEmpty())
353  break;
354  QScriptValueList objects;
355  QString prefix = path.last();
356  QSet<QString> matches;
357  if (path.size() > 1) {
358  const QString &topLevelIdent = path.at(0);
359  QScriptValue obj;
360  if (topLevelIdent == QLatin1String("this")) {
361  obj = ctx->thisObject();
362  } else {
363  QScriptValueList scopeChain;
364  scopeChain = ctx->scopeChain();
365  for (int i = 0; i < scopeChain.size(); ++i) {
366  QScriptValue oo = scopeChain.at(i).property(topLevelIdent);
367  if (oo.isObject()) {
368  obj = oo;
369  break;
370  }
371  }
372  }
373  for (int i = 1; obj.isObject() && (i < path.size()-1); ++i)
374  obj = obj.property(path.at(i));
375  if (obj.isValid())
376  objects.append(obj);
377  } else {
378  objects << ctx->scopeChain();
380  keywords.append(QString::fromLatin1("this"));
381  keywords.append(QString::fromLatin1("true"));
382  keywords.append(QString::fromLatin1("false"));
383  keywords.append(QString::fromLatin1("null"));
384  for (int i = 0; i < keywords.size(); ++i) {
385  const QString &kwd = keywords.at(i);
386  if (isPrefixOf(prefix, kwd))
387  matches.insert(kwd);
388  }
389  }
390 
391  for (int i = 0; i < objects.size(); ++i) {
392  QScriptValue obj = objects.at(i);
393  while (obj.isObject()) {
395  while (it.hasNext()) {
396  it.next();
397  QString propertyName = it.name();
398  if (isPrefixOf(prefix, propertyName))
399  matches.insert(propertyName);
400  }
401  obj = obj.prototype();
402  }
403  }
404  QStringList matchesList = matches.toList();
405  qStableSort(matchesList);
406  response.setResult(matchesList);
407  } break;
408 
410  int id = backend->newScriptObjectSnapshot();
411  response.setResult(id);
412  } break;
413 
415  int id = command.snapshotId();
416  QScriptObjectSnapshot *snap = backend->scriptObjectSnapshot(id);
417  Q_ASSERT(snap != 0);
418  QScriptDebuggerValue object = command.scriptValue();
420  QScriptEngine *engine = backend->engine();
421  QScriptValue realObject = object.toScriptValue(engine);
422  Q_ASSERT(realObject.isObject());
423  QScriptObjectSnapshot::Delta delta = snap->capture(realObject);
425  result.removedProperties = delta.removedProperties;
426  bool didIgnoreExceptions = backend->ignoreExceptions();
427  backend->setIgnoreExceptions(true);
428  for (int i = 0; i < delta.changedProperties.size(); ++i) {
429  const QScriptValueProperty &src = delta.changedProperties.at(i);
430  bool hadException = engine->hasUncaughtException();
431  QString str = src.value().toString();
432  if (!hadException && engine->hasUncaughtException())
433  engine->clearExceptions();
434  QScriptDebuggerValueProperty dest(src.name(), src.value(), str, src.flags());
435  result.changedProperties.append(dest);
436  }
437  for (int j = 0; j < delta.addedProperties.size(); ++j) {
438  const QScriptValueProperty &src = delta.addedProperties.at(j);
439  bool hadException = engine->hasUncaughtException();
440  QString str = src.value().toString();
441  if (!hadException && engine->hasUncaughtException())
442  engine->clearExceptions();
443  QScriptDebuggerValueProperty dest(src.name(), src.value(), str, src.flags());
444  result.addedProperties.append(dest);
445  }
446  backend->setIgnoreExceptions(didIgnoreExceptions);
447  response.setResult(QVariant::fromValue(result));
448  } break;
449 
451  int id = command.snapshotId();
452  backend->deleteScriptObjectSnapshot(id);
453  } break;
454 
456  QScriptDebuggerValue object = command.scriptValue();
458  QScriptEngine *engine = backend->engine();
459  QScriptValue realObject = object.toScriptValue(engine);
460  Q_ASSERT(realObject.isObject());
461  int id = backend->newScriptValueIterator(realObject);
462  response.setResult(id);
463  } break;
464 
466  int id = command.iteratorId();
467  int count = 1000;
469  Q_ASSERT(it != 0);
471  for (int i = 0; (i < count) && it->hasNext(); ++i) {
472  it->next();
473  QString name = it->name();
474  QScriptValue value = it->value();
475  QString valueAsString = value.toString();
476  QScriptValue::PropertyFlags flags = it->flags();
477  QScriptDebuggerValueProperty prp(name, value, valueAsString, flags);
478  props.append(prp);
479  }
480  response.setResult(props);
481  } break;
482 
484  int id = command.iteratorId();
485  backend->deleteScriptValueIterator(id);
486  } break;
487 
489  int contextIndex = command.contextIndex();
490  QString program = command.program();
491  QString fileName = command.fileName();
492  int lineNumber = command.lineNumber();
493  backend->evaluate(contextIndex, program, fileName, lineNumber);
494  response.setAsync(true);
495  } break;
496 
498  QScriptDebuggerValue value = command.scriptValue();
499  QScriptEngine *engine = backend->engine();
500  QScriptValue realValue = value.toScriptValue(engine);
501  response.setResult(realValue.toString());
502  } break;
503 
505  QScriptDebuggerValue object = command.scriptValue();
506  QScriptEngine *engine = backend->engine();
507  QScriptValue realObject = object.toScriptValue(engine);
509  QScriptValue realValue = value.toScriptValue(engine);
510  QString name = command.name();
511  realObject.setProperty(name, realValue);
512  } break;
513 
515  backend->engine()->clearExceptions();
516  break;
517 
520  break;
521  }
522  return response;
523 }
524 
The QVariant class acts like a union for the most common Qt data types.
Definition: qvariant.h:92
The QScriptContext class represents a Qt Script function invocation.
void stepOut()
Steps out of the current script function.
QScriptDebuggerValue scriptValue() const
QScriptObjectSnapshot * scriptObjectSnapshot(int id) const
QScriptValue property(const QString &name, const ResolveFlags &mode=ResolvePrototype) const
Returns the value of this QScriptValue&#39;s property with the given name, using the given mode to resolv...
int type
Definition: qmetatype.cpp:239
virtual QScriptDebuggerResponse execute(QScriptDebuggerBackend *backend, const QScriptDebuggerCommand &command)
Applies the given command to the given backend.
QScriptContextsDelta contextsCheckpoint()
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
int functionEndLineNumber() const
Returns the line number where the definition of the called function ends, or -1 if the line number is...
#define it(className, varName)
QScriptValue toScriptValue(QScriptEngine *engine) const
Converts this QScriptDebuggerValue to a QScriptValue in the given engine and returns the resulting va...
QScriptValue callee() const
Returns the callee.
QScriptValueList scopeChain() const
Returns the scope chain of this QScriptContext.
void stepInto(int count=1)
Steps into the next script statement.
QScriptBreakpointMap breakpoints() const
Returns this backend&#39;s breakpoints.
The QScriptDebuggerResponse class represents a front-end&#39;s response to a QScriptDebuggerCommand.
int length() const
Returns the number of characters in this string.
Definition: qstring.h:696
void interruptEvaluation()
Interrupts script evaluation.
QString toString() const
Returns the string value of this QScriptValue, as defined in ECMA-262 section 9.8, "ToString".
int lineNumber() const
Returns the LineNumber attribute of this command converted to an int.
QString name() const
Returns the name of the last property that was jumped over using next() or previous().
bool startsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string starts with s; otherwise returns false.
Definition: qstring.cpp:3734
void deleteAllBreakpoints()
Deletes all breakpoints.
QLatin1String(DBUS_INTERFACE_DBUS))) Q_GLOBAL_STATIC_WITH_ARGS(QString
qint64 resolveScript(const QString &fileName) const
void returnToCaller(int contextIndex, const QScriptValue &value)
void runToLocation(const QString &fileName, int lineNumber)
Continues evaluation until the location defined by the given fileName and lineNumber is reached...
QScriptValueIterator * scriptValueIterator(int id) const
The QString class provides a Unicode character string.
Definition: qstring.h:83
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
QScriptContext * context(int index) const
Returns the context for the frame with the given index.
QScriptEngine * engine() const
Returns the script engine that this backend is attached to, or 0 if the backend is not attached to an...
void continueEvalution()
Continues script evaluation.
Type type() const
Returns the type of this command.
QString name() const
Returns the name of this QScriptValueProperty.
bool isEmpty() const
Returns true if the list contains no items; otherwise returns false.
Definition: qlist.h:152
int toInt(bool *ok=0) const
Returns the variant as an int if the variant has type() Int , Bool , ByteArray , Char ...
Definition: qvariant.cpp:2625
int contextCount() const
Returns the number of contexts (frames).
The QScriptScriptData class holds data associated with a script.
QScriptValue::PropertyFlags flags() const
Returns the flags of this QScriptValueProperty.
QString fileName() const
Returns the FileName attribute of this command converted to a string.
QStringList toStringList() const
Returns the variant as a QStringList if the variant has type() StringList, String ...
Definition: qvariant.cpp:2259
QScriptBreakpointData breakpointData(int id) const
Returns the data associated with the breakpoint identified by the given id.
void append(const T &t)
Inserts value at the end of the list.
Definition: qlist.h:507
The QScriptEngine class provides an environment for evaluating Qt Script code.
void evaluate(int contextIndex, const QString &program, const QString &fileName, int lineNumber)
Evaluates the given program.
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
QList< T > toList() const
Definition: qset.h:296
const char * name
const T & at(int i) const
Returns the item at index position i in the list.
Definition: qlist.h:468
QScriptScriptsDelta scriptsDelta() const
Returns the difference between the latest scripts checkpoint and the previous checkpoint.
The QStringList class provides a list of strings.
Definition: qstringlist.h:66
void setError(Error error)
Sets the error code of this response.
const_iterator insert(const T &value)
Definition: qset.h:179
static const char * data(const QByteArray &arr)
static bool isPrefixOf(const QString &prefix, const QString &what)
__int64 qint64
Definition: qglobal.h:942
The QScriptBreakpointData class contains data associated with a breakpoint.
void setIgnoreExceptions(bool ignore)
static QVariant fromValue(const T &value)
Returns a QVariant containing a copy of value.
Definition: qvariant.h:336
void stepOver(int count=1)
Steps over the next script statement.
bool setBreakpointData(int id, const QScriptBreakpointData &data)
Sets the data associated with the breakpoint identified by the given id.
QStringList backtrace() const
Returns a backtrace of the current execution.
bool isEvaluating() const
Returns true if this engine is currently evaluating a script, otherwise returns false.
virtual void resume()=0
This function is called when control should be returned back to the back-end, i.
#define Q_DECLARE_METATYPE(TYPE)
This macro makes the type Type known to QMetaType as long as it provides a public default constructor...
Definition: qmetatype.h:265
int functionStartLineNumber() const
Returns the line number where the definition of the called function starts, or -1 if the line number ...
ExecutionState state() const
Returns the frameution state of this QScriptContext.
void qStableSort(RandomAccessIterator start, RandomAccessIterator end)
Definition: qalgorithms.h:202
The QScriptDebuggerCommand class represents a command issued to a QScriptDebuggerFrontend.
QScriptValue::PropertyFlags flags() const
Returns the flags of the last property that was jumped over using next() or previous().
The QScriptDebuggerValue class represents a script value.
void setProperty(const QString &name, const QScriptValue &value, const PropertyFlags &flags=KeepExistingFlags)
Sets the value of this QScriptValue&#39;s property with the given name to the given value.
The QScriptContextInfo class provides additional information about a QScriptContext.
QScriptScriptMap scripts() const
Returns the scripts that this backend knows about.
The QScriptValueIterator class provides a Java-style iterator for QScriptValue.
The QScriptDebuggerBackend class is the base class of debugger back-ends.
QScriptValue value() const
Returns the value of this QScriptValueProperty.
void setResult(const QVariant &value)
Sets the Result attribute of this response to the given value.
PropertyFlags
Definition: qmetaobject_p.h:61
QScriptDebuggerValue subordinateScriptValue() const
static QString fromLatin1(const char *, int size=-1)
Returns a QString initialized with the first size characters of the Latin-1 string str...
Definition: qstring.cpp:4188
static const char *const keywords[MAX_KEYWORD]
void scriptsCheckpoint()
Makes a checkpoint of the currently loaded scripts.
#define ctx
Definition: qgl.cpp:6094
QScriptValue value() const
Returns the value of the last property that was jumped over using next() or previous().
T & last()
Returns a reference to the last item in the list.
Definition: qlist.h:284
int size() const
Returns the number of items in the list.
Definition: qlist.h:137
bool isEmpty() const
Returns true if the map contains no items; otherwise returns false.
Definition: qmap.h:203
Delta capture(const QScriptValue &object)
QVariant attribute(Attribute attribute, const QVariant &defaultValue=QVariant()) const
Returns the value of the given attribute, or defaultValue if the attribute is not defined...
void clearExceptions()
Clears any uncaught exceptions in this engine.
QList< qint64 > contextIds() const
QScriptValue activationObject() const
Returns the activation object of this QScriptContext.
QScriptScriptData scriptData(qint64 id) const
Returns the data for the script identified by the given id.
int newScriptValueIterator(const QScriptValue &object)
bool deleteBreakpoint(int id)
Deletes the breakpoint identified by the given id.
bool isValid() const
Returns true if the storage type of this variant is not QVariant::Invalid; otherwise returns false...
Definition: qvariant.h:485
QScriptValue thisObject() const
Returns the `this&#39; object associated with this QScriptContext.
qint64 scriptId() const
Returns the ScriptID attribute of this command converted to a qint64.
bool hasUncaughtException() const
Returns true if the last script evaluation resulted in an uncaught exception; otherwise returns false...
The QScriptValue class acts as a container for the Qt Script data types.
Definition: qscriptvalue.h:57
QScriptBreakpointData breakpointData() const
static QString fileName(const QString &fileUrl)
bool isValid() const
Returns true if this QScriptValue is valid; otherwise returns false.
void next()
Advances the iterator by one position.
bool isObject() const
Returns true if this QScriptValue is of the Object type; otherwise returns false. ...
bool hasNext() const
Returns true if there is at least one item ahead of the iterator (i.e.
int setBreakpoint(const QScriptBreakpointData &data)
Sets a breakpoint defined by the given data, and returns a unique identifier for the new breakpoint...
QScriptValue prototype() const
If this QScriptValue is an object, returns the internal prototype (__proto__ property) of this object...