void QScriptDebuggerCodeWidgetPrivate::_q_onBreakpointEnableRequest(int lineNumber, bool enable) { QScriptDebuggerCodeViewInterface *view = qobject_cast<QScriptDebuggerCodeViewInterface*>(q_func()->sender()); qint64 sid = scriptId(view); int bpid = breakpointsModel->resolveBreakpoint(sid, lineNumber); if (bpid == -1) bpid = breakpointsModel->resolveBreakpoint(scriptsModel->scriptData(sid).fileName(), lineNumber); Q_ASSERT(bpid != -1); QScriptBreakpointData data = breakpointsModel->breakpointData(bpid); data.setEnabled(enable); breakpointsModel->setBreakpointData(bpid, data); }
void QScriptDebuggerCodeWidgetPrivate::_q_onBreakpointsDataChanged( const QModelIndex &tl, const QModelIndex &br) { for (int i = tl.row(); i <= br.row(); ++i) { QScriptBreakpointData data = breakpointsModel->breakpointDataAt(i); qint64 scriptId = data.scriptId(); if (scriptId == -1) { scriptId = scriptsModel->resolveScript(data.fileName()); if (scriptId == -1) continue; } QScriptDebuggerCodeViewInterface *view = viewHash.value(scriptId); if (!view) continue; view->setBreakpointEnabled(data.lineNumber(), data.isEnabled()); } }
void QScriptDebuggerCodeWidgetPrivate::_q_onBreakpointsInserted( const QModelIndex &, int first, int last) { for (int i = first; i <= last; ++i) { QScriptBreakpointData data = breakpointsModel->breakpointDataAt(i); qint64 scriptId = data.scriptId(); if (scriptId == -1) { scriptId = scriptsModel->resolveScript(data.fileName()); if (scriptId == -1) continue; } QScriptDebuggerCodeViewInterface *view = viewHash.value(scriptId); if (!view) continue; view->setBreakpoint(data.lineNumber()); } }
/*! Sets a breakpoint defined by the given \a data, and returns a unique identifier for the new breakpoint. If the conditions of the breakpoint is satisfied at some point during script evaluation, a breakpoint event() will be generated. \sa deleteBreakpoint(), breakpoints() */ int QScriptDebuggerBackend::setBreakpoint(const QScriptBreakpointData &data) { Q_D(QScriptDebuggerBackend); if (!d->agent) return -1; if (!data.isValid()) return -1; return d->agent->setBreakpoint(data); }
/*! \reimp */ bool QScriptBreakpointsModel::setData(const QModelIndex &index, const QVariant &value, int role) { Q_D(QScriptBreakpointsModel); if (!index.isValid() || (index.row() >= d->breakpoints.size())) return false; const QPair<int, QScriptBreakpointData> &item = d->breakpoints.at(index.row()); QScriptBreakpointData modifiedData; int col = index.column(); if ((col == 0) || (col == 4)) { if (role == Qt::CheckStateRole) { modifiedData = item.second; if (col == 0) modifiedData.setEnabled(value.toInt() == Qt::Checked); else modifiedData.setSingleShot(value.toInt() == Qt::Checked); } } else if (col == 2) { if (role == Qt::EditRole) { modifiedData = item.second; modifiedData.setCondition(value.toString()); } } else if (col == 3) { if (role == Qt::EditRole) { modifiedData = item.second; modifiedData.setIgnoreCount(value.toInt()); } } if (!modifiedData.isValid()) return false; QScriptDebuggerJob *job = new SetBreakpointDataJob(item.first, modifiedData, d->commandScheduler); d->jobScheduler->scheduleJob(job); return true; }
/*! Sets a breakpoint defined by the given \a data. Returns an integer that uniquely identifies the new breakpoint, or -1 if setting the breakpoint failed. */ int QScriptDebuggerAgent::setBreakpoint(const QScriptBreakpointData &data) { Q_D(QScriptDebuggerAgent); qint64 scriptId = data.scriptId(); if (scriptId != -1) { if (!d->scripts.contains(scriptId)) { // that script has been unloaded, so invalidate the ID scriptId = -1; const_cast<QScriptBreakpointData&>(data).setScriptId(-1); } else if (data.fileName().isEmpty()) { QString fileName = d->scripts[scriptId].fileName(); const_cast<QScriptBreakpointData&>(data).setFileName(fileName); } } int id = d->nextBreakpointId; ++d->nextBreakpointId; if (scriptId != -1) { d->resolvedBreakpoints[scriptId].append(id); } else { QString fileName = data.fileName(); bool resolved = false; QScriptScriptMap::const_iterator it; for (it = d->scripts.constBegin(); it != d->scripts.constEnd(); ++it) { if (it.value().fileName() == fileName) { d->resolvedBreakpoints[it.key()].append(id); resolved = true; break; } } if (!resolved) d->unresolvedBreakpoints[fileName].append(id); } d->breakpoints.insert(id, data); return id; }
static QScriptValue breakpointDataToScriptValue(QScriptEngine *eng, const QScriptBreakpointData &in) { QScriptValue out = eng->newObject(); out.setProperty(QString::fromLatin1("scriptId"), QScriptValue(eng, qsreal(in.scriptId()))); out.setProperty(QString::fromLatin1("fileName"), QScriptValue(eng, in.fileName())); out.setProperty(QString::fromLatin1("lineNumber"), QScriptValue(eng, in.lineNumber())); out.setProperty(QString::fromLatin1("enabled"), QScriptValue(eng, in.isEnabled())); out.setProperty(QString::fromLatin1("singleShot"), QScriptValue(eng, in.isSingleShot())); out.setProperty(QString::fromLatin1("ignoreCount"), QScriptValue(eng, in.ignoreCount())); out.setProperty(QString::fromLatin1("condition"), QScriptValue(eng, in.condition())); return out; }
static void breakpointDataFromScriptValue(const QScriptValue &in, QScriptBreakpointData &out) { QScriptValue scriptId = in.property(QString::fromLatin1("scriptId")); if (scriptId.isValid()) out.setScriptId((qint64)scriptId.toNumber()); out.setFileName(in.property(QString::fromLatin1("fileName")).toString()); out.setLineNumber(in.property(QString::fromLatin1("lineNumber")).toInt32()); QScriptValue enabled = in.property(QString::fromLatin1("enabled")); if (enabled.isValid()) out.setEnabled(enabled.toBoolean()); QScriptValue singleShot = in.property(QString::fromLatin1("singleShot")); if (singleShot.isValid()) out.setSingleShot(singleShot.toBoolean()); out.setIgnoreCount(in.property(QString::fromLatin1("ignoreCount")).toInt32()); out.setCondition(in.property(QString::fromLatin1("condition")).toString()); }
/*! Returns true if this QScriptBreakpointData is equal to the \a other data, otherwise returns false. */ bool QScriptBreakpointData::operator==(const QScriptBreakpointData &other) const { Q_D(const QScriptBreakpointData); const QScriptBreakpointDataPrivate *od = other.d_func(); if (d == od) return true; if (!d || !od) return false; return ((d->scriptId == od->scriptId) && (d->fileName == od->fileName) && (d->lineNumber == od->lineNumber) && (d->enabled == od->enabled) && (d->singleShot == od->singleShot) && (d->condition == od->condition) && (d->ignoreCount == od->ignoreCount) && (d->data == od->data) && (d->hitCount == od->hitCount)); }
/*! Applies the given \a command to the given \a backend. */ QScriptDebuggerResponse QScriptDebuggerCommandExecutor::execute( QScriptDebuggerBackend *backend, const QScriptDebuggerCommand &command) { QScriptDebuggerResponse response; switch (command.type()) { case QScriptDebuggerCommand::None: break; case QScriptDebuggerCommand::Interrupt: backend->interruptEvaluation(); break; case QScriptDebuggerCommand::Continue: if (backend->engine()->isEvaluating()) { backend->continueEvalution(); response.setAsync(true); } break; case QScriptDebuggerCommand::StepInto: { QVariant attr = command.attribute(QScriptDebuggerCommand::StepCount); int count = attr.isValid() ? attr.toInt() : 1; backend->stepInto(count); response.setAsync(true); } break; case QScriptDebuggerCommand::StepOver: { QVariant attr = command.attribute(QScriptDebuggerCommand::StepCount); int count = attr.isValid() ? attr.toInt() : 1; backend->stepOver(count); response.setAsync(true); } break; case QScriptDebuggerCommand::StepOut: backend->stepOut(); response.setAsync(true); break; case QScriptDebuggerCommand::RunToLocation: backend->runToLocation(command.fileName(), command.lineNumber()); response.setAsync(true); break; case QScriptDebuggerCommand::RunToLocationByID: backend->runToLocation(command.scriptId(), command.lineNumber()); response.setAsync(true); break; case QScriptDebuggerCommand::ForceReturn: { int contextIndex = command.contextIndex(); QScriptDebuggerValue value = command.scriptValue(); QScriptEngine *engine = backend->engine(); QScriptValue realValue = value.toScriptValue(engine); backend->returnToCaller(contextIndex, realValue); response.setAsync(true); } break; case QScriptDebuggerCommand::Resume: backend->resume(); response.setAsync(true); break; case QScriptDebuggerCommand::SetBreakpoint: { QScriptBreakpointData data = command.breakpointData(); if (!data.isValid()) data = QScriptBreakpointData(command.fileName(), command.lineNumber()); int id = backend->setBreakpoint(data); response.setResult(id); } break; case QScriptDebuggerCommand::DeleteBreakpoint: { int id = command.breakpointId(); if (!backend->deleteBreakpoint(id)) response.setError(QScriptDebuggerResponse::InvalidBreakpointID); } break; case QScriptDebuggerCommand::DeleteAllBreakpoints: backend->deleteAllBreakpoints(); break; case QScriptDebuggerCommand::GetBreakpoints: { QScriptBreakpointMap bps = backend->breakpoints(); if (!bps.isEmpty()) response.setResult(bps); } break; case QScriptDebuggerCommand::GetBreakpointData: { int id = command.breakpointId(); QScriptBreakpointData data = backend->breakpointData(id); if (data.isValid()) response.setResult(data); else response.setError(QScriptDebuggerResponse::InvalidBreakpointID); } break; case QScriptDebuggerCommand::SetBreakpointData: { int id = command.breakpointId(); QScriptBreakpointData data = command.breakpointData(); if (!backend->setBreakpointData(id, data)) response.setError(QScriptDebuggerResponse::InvalidBreakpointID); } break; case QScriptDebuggerCommand::GetScripts: { QScriptScriptMap scripts = backend->scripts(); if (!scripts.isEmpty()) response.setResult(scripts); } break; case QScriptDebuggerCommand::GetScriptData: { qint64 id = command.scriptId(); QScriptScriptData data = backend->scriptData(id); if (data.isValid()) response.setResult(data); else response.setError(QScriptDebuggerResponse::InvalidScriptID); } break; case QScriptDebuggerCommand::ScriptsCheckpoint: backend->scriptsCheckpoint(); response.setResult(QVariant::fromValue(backend->scriptsDelta())); break; case QScriptDebuggerCommand::GetScriptsDelta: response.setResult(QVariant::fromValue(backend->scriptsDelta())); break; case QScriptDebuggerCommand::ResolveScript: response.setResult(backend->resolveScript(command.fileName())); break; case QScriptDebuggerCommand::GetBacktrace: response.setResult(backend->backtrace()); break; case QScriptDebuggerCommand::GetContextCount: response.setResult(backend->contextCount()); break; case QScriptDebuggerCommand::GetContextState: { QScriptContext *ctx = backend->context(command.contextIndex()); if (ctx) response.setResult(static_cast<int>(ctx->state())); else response.setError(QScriptDebuggerResponse::InvalidContextIndex); } break; case QScriptDebuggerCommand::GetContextID: { int idx = command.contextIndex(); if ((idx >= 0) && (idx < backend->contextCount())) response.setResult(backend->contextIds()[idx]); else response.setError(QScriptDebuggerResponse::InvalidContextIndex); } break; case QScriptDebuggerCommand::GetContextInfo: { QScriptContext *ctx = backend->context(command.contextIndex()); if (ctx) response.setResult(QScriptContextInfo(ctx)); else response.setError(QScriptDebuggerResponse::InvalidContextIndex); } break; case QScriptDebuggerCommand::GetThisObject: { QScriptContext *ctx = backend->context(command.contextIndex()); if (ctx) response.setResult(ctx->thisObject()); else response.setError(QScriptDebuggerResponse::InvalidContextIndex); } break; case QScriptDebuggerCommand::GetActivationObject: { QScriptContext *ctx = backend->context(command.contextIndex()); if (ctx) response.setResult(ctx->activationObject()); else response.setError(QScriptDebuggerResponse::InvalidContextIndex); } break; case QScriptDebuggerCommand::GetScopeChain: { QScriptContext *ctx = backend->context(command.contextIndex()); if (ctx) { QScriptDebuggerValueList dest; QScriptValueList src = ctx->scopeChain(); for (int i = 0; i < src.size(); ++i) dest.append(src.at(i)); response.setResult(dest); } else { response.setError(QScriptDebuggerResponse::InvalidContextIndex); } } break; case QScriptDebuggerCommand::ContextsCheckpoint: { response.setResult(QVariant::fromValue(backend->contextsCheckpoint())); } break; case QScriptDebuggerCommand::GetPropertyExpressionValue: { QScriptContext *ctx = backend->context(command.contextIndex()); int lineNumber = command.lineNumber(); QVariant attr = command.attribute(QScriptDebuggerCommand::UserAttribute); QStringList path = attr.toStringList(); if (!ctx || path.isEmpty()) break; QScriptContextInfo ctxInfo(ctx); if (ctx->callee().isValid() && ((lineNumber < ctxInfo.functionStartLineNumber()) || (lineNumber > ctxInfo.functionEndLineNumber()))) { break; } QScriptValueList objects; int pathIndex = 0; if (path.at(0) == QLatin1String("this")) { objects.append(ctx->thisObject()); ++pathIndex; } else { objects << ctx->scopeChain(); } for (int i = 0; i < objects.size(); ++i) { QScriptValue val = objects.at(i); for (int j = pathIndex; val.isValid() && (j < path.size()); ++j) { val = val.property(path.at(j)); } if (val.isValid()) { bool hadException = (ctx->state() == QScriptContext::ExceptionState); QString str = val.toString(); if (!hadException && backend->engine()->hasUncaughtException()) backend->engine()->clearExceptions(); response.setResult(str); break; } } } break; case QScriptDebuggerCommand::GetCompletions: { QScriptContext *ctx = backend->context(command.contextIndex()); QVariant attr = command.attribute(QScriptDebuggerCommand::UserAttribute); QStringList path = attr.toStringList(); if (!ctx || path.isEmpty()) break; QScriptValueList objects; QString prefix = path.last(); QSet<QString> matches; if (path.size() > 1) { const QString &topLevelIdent = path.at(0); QScriptValue obj; if (topLevelIdent == QLatin1String("this")) { obj = ctx->thisObject(); } else { QScriptValueList scopeChain; scopeChain = ctx->scopeChain(); for (int i = 0; i < scopeChain.size(); ++i) { QScriptValue oo = scopeChain.at(i).property(topLevelIdent); if (oo.isObject()) { obj = oo; break; } } } for (int i = 1; obj.isObject() && (i < path.size()-1); ++i) obj = obj.property(path.at(i)); if (obj.isValid()) objects.append(obj); } else { objects << ctx->scopeChain(); QStringList keywords; keywords.append(QString::fromLatin1("this")); keywords.append(QString::fromLatin1("true")); keywords.append(QString::fromLatin1("false")); keywords.append(QString::fromLatin1("null")); for (int i = 0; i < keywords.size(); ++i) { const QString &kwd = keywords.at(i); if (isPrefixOf(prefix, kwd)) matches.insert(kwd); } } for (int i = 0; i < objects.size(); ++i) { QScriptValue obj = objects.at(i); while (obj.isObject()) { QScriptValueIterator it(obj); while (it.hasNext()) { it.next(); QString propertyName = it.name(); if (isPrefixOf(prefix, propertyName)) matches.insert(propertyName); } obj = obj.prototype(); } } QStringList matchesList = matches.toList(); qStableSort(matchesList); response.setResult(matchesList); } break; case QScriptDebuggerCommand::NewScriptObjectSnapshot: { int id = backend->newScriptObjectSnapshot(); response.setResult(id); } break; case QScriptDebuggerCommand::ScriptObjectSnapshotCapture: { int id = command.snapshotId(); QScriptObjectSnapshot *snap = backend->scriptObjectSnapshot(id); Q_ASSERT(snap != 0); QScriptDebuggerValue object = command.scriptValue(); Q_ASSERT(object.type() == QScriptDebuggerValue::ObjectValue); QScriptEngine *engine = backend->engine(); QScriptValue realObject = object.toScriptValue(engine); Q_ASSERT(realObject.isObject()); QScriptObjectSnapshot::Delta delta = snap->capture(realObject); QScriptDebuggerObjectSnapshotDelta result; result.removedProperties = delta.removedProperties; bool didIgnoreExceptions = backend->ignoreExceptions(); backend->setIgnoreExceptions(true); for (int i = 0; i < delta.changedProperties.size(); ++i) { const QScriptValueProperty &src = delta.changedProperties.at(i); bool hadException = engine->hasUncaughtException(); QString str = src.value().toString(); if (!hadException && engine->hasUncaughtException()) engine->clearExceptions(); QScriptDebuggerValueProperty dest(src.name(), src.value(), str, src.flags()); result.changedProperties.append(dest); } for (int j = 0; j < delta.addedProperties.size(); ++j) { const QScriptValueProperty &src = delta.addedProperties.at(j); bool hadException = engine->hasUncaughtException(); QString str = src.value().toString(); if (!hadException && engine->hasUncaughtException()) engine->clearExceptions(); QScriptDebuggerValueProperty dest(src.name(), src.value(), str, src.flags()); result.addedProperties.append(dest); } backend->setIgnoreExceptions(didIgnoreExceptions); response.setResult(QVariant::fromValue(result)); } break; case QScriptDebuggerCommand::DeleteScriptObjectSnapshot: { int id = command.snapshotId(); backend->deleteScriptObjectSnapshot(id); } break; case QScriptDebuggerCommand::NewScriptValueIterator: { QScriptDebuggerValue object = command.scriptValue(); Q_ASSERT(object.type() == QScriptDebuggerValue::ObjectValue); QScriptEngine *engine = backend->engine(); QScriptValue realObject = object.toScriptValue(engine); Q_ASSERT(realObject.isObject()); int id = backend->newScriptValueIterator(realObject); response.setResult(id); } break; case QScriptDebuggerCommand::GetPropertiesByIterator: { int id = command.iteratorId(); int count = 1000; QScriptValueIterator *it = backend->scriptValueIterator(id); Q_ASSERT(it != 0); QScriptDebuggerValuePropertyList props; for (int i = 0; (i < count) && it->hasNext(); ++i) { it->next(); QString name = it->name(); QScriptValue value = it->value(); QString valueAsString = value.toString(); QScriptValue::PropertyFlags flags = it->flags(); QScriptDebuggerValueProperty prp(name, value, valueAsString, flags); props.append(prp); } response.setResult(props); } break; case QScriptDebuggerCommand::DeleteScriptValueIterator: { int id = command.iteratorId(); backend->deleteScriptValueIterator(id); } break; case QScriptDebuggerCommand::Evaluate: { int contextIndex = command.contextIndex(); QString program = command.program(); QString fileName = command.fileName(); int lineNumber = command.lineNumber(); backend->evaluate(contextIndex, program, fileName, lineNumber); response.setAsync(true); } break; case QScriptDebuggerCommand::ScriptValueToString: { QScriptDebuggerValue value = command.scriptValue(); QScriptEngine *engine = backend->engine(); QScriptValue realValue = value.toScriptValue(engine); response.setResult(realValue.toString()); } break; case QScriptDebuggerCommand::SetScriptValueProperty: { QScriptDebuggerValue object = command.scriptValue(); QScriptEngine *engine = backend->engine(); QScriptValue realObject = object.toScriptValue(engine); QScriptDebuggerValue value = command.subordinateScriptValue(); QScriptValue realValue = value.toScriptValue(engine); QString name = command.name(); realObject.setProperty(name, realValue); } break; case QScriptDebuggerCommand::ClearExceptions: backend->engine()->clearExceptions(); break; case QScriptDebuggerCommand::UserCommand: case QScriptDebuggerCommand::MaxUserCommand: break; } return response; }