📄 kjs_debugwin.cpp
字号:
return (m_mode != Stop);}bool KJSDebugWin::sourceUnused(KJS::ExecState *exec, int sourceId){ // Verify that there aren't any contexts on the stack using the given sourceId // This should never be the case because this function is only called when // the interpreter has deleted all Node objects for the source. for (int e = 0; e < m_execsCount; e++) assert(m_execs[e]->context().sourceId() != sourceId); // Now remove the fragment (and the SourceFile, if it was the last fragment in that file) SourceFragment *fragment = m_sourceFragments[sourceId]; if (fragment) { m_sourceFragments.erase(sourceId); SourceFile *sourceFile = fragment->sourceFile; if (sourceFile->hasOneRef()) { for (int i = 0; i < m_sourceSel->count(); i++) { if (m_sourceSelFiles.at(i) == sourceFile) { m_sourceSel->removeItem(i); m_sourceSelFiles.remove(i); break; } } removeSourceFile(exec->interpreter(),sourceFile->url); } delete fragment; } return (m_mode != Stop);}bool KJSDebugWin::exception(ExecState *exec, const Value &value, bool inTryCatch){ assert(value.isValid()); // Ignore exceptions that will be caught by the script if (inTryCatch) return true; KParts::ReadOnlyPart *part = static_cast<ScriptInterpreter*>(exec->interpreter())->part(); KHTMLPart *khtmlpart = ::qt_cast<KHTMLPart*>(part); if (khtmlpart && !khtmlpart->settings()->isJavaScriptErrorReportingEnabled()) return true; QWidget *dlgParent = (m_evalDepth == 0) ? (QWidget*)part->widget() : (QWidget*)this; QString exceptionMsg = value.toString(exec).qstring(); // Syntax errors are a special case. For these we want to display the url & lineno, // which isn't included in the exception messeage. So we work it out from the values // passed to sourceParsed() Object valueObj = Object::dynamicCast(value); Object syntaxError = exec->interpreter()->builtinSyntaxError(); if (valueObj.isValid() && valueObj.get(exec,"constructor").imp() == syntaxError.imp()) { Value sidValue = valueObj.get(exec,"sid"); if (sidValue.isA(NumberType)) { // sid is not set for Function() constructor int sourceId = (int)sidValue.toNumber(exec); assert(m_sourceFragments[sourceId]); exceptionMsg = i18n("Parse error at %1 line %2") .arg(m_sourceFragments[sourceId]->sourceFile->url) .arg(m_sourceFragments[sourceId]->baseLine+m_sourceFragments[sourceId]->errorLine-1); } } bool dontShowAgain = false; if (m_execsCount == 0) { // An exception occurred and we're not currently executing any code... this can // happen in some cases e.g. a parse error, or native code accessing funcitons like // Object::put() QString msg = i18n("An error occurred while attempting to run a script on this page.\n\n%1") .arg(exceptionMsg); KJSErrorDialog dlg(dlgParent,msg,false); dlg.exec(); dontShowAgain = dlg.dontShowAgain(); } else { Context ctx = m_execs[m_execsCount-1]->context(); SourceFragment *sourceFragment = m_sourceFragments[ctx.sourceId()]; QString msg = i18n("An error occurred while attempting to run a script on this page.\n\n%1 line %2:\n%3") .arg(KStringHandler::rsqueeze( sourceFragment->sourceFile->url,80), QString::number( sourceFragment->baseLine+ctx.curStmtFirstLine()-1), exceptionMsg); KJSErrorDialog dlg(dlgParent,msg,true); dlg.exec(); dontShowAgain = dlg.dontShowAgain(); if (dlg.debugSelected()) { m_mode = Next; m_steppingDepth = m_execsCount-1; enterSession(exec); } } if (dontShowAgain) { KConfig *config = kapp->config(); KConfigGroupSaver saver(config,QString::fromLatin1("Java/JavaScript Settings")); config->writeEntry("ReportJavaScriptErrors",QVariant(false,0)); config->sync(); QByteArray data; kapp->dcopClient()->send( "konqueror*", "KonquerorIface", "reparseConfiguration()", data ); } return (m_mode != Stop);}bool KJSDebugWin::atStatement(KJS::ExecState *exec){ assert(m_execsCount > 0); assert(m_execs[m_execsCount-1] == exec); checkBreak(exec); return (m_mode != Stop);}bool KJSDebugWin::enterContext(ExecState *exec){ if (m_execsCount >= m_execsAlloc) { m_execsAlloc += 10; m_execs = (ExecState**)realloc(m_execs,m_execsAlloc*sizeof(ExecState*)); } m_execs[m_execsCount++] = exec; if (m_mode == Step) m_steppingDepth = m_execsCount-1; checkBreak(exec); return (m_mode != Stop);}bool KJSDebugWin::exitContext(ExecState *exec, const Completion &/*completion*/){ assert(m_execsCount > 0); assert(m_execs[m_execsCount-1] == exec); checkBreak(exec); m_execsCount--; if (m_steppingDepth > m_execsCount-1) m_steppingDepth = m_execsCount-1; if (m_execsCount == 0) updateContextList(); return (m_mode != Stop);}void KJSDebugWin::displaySourceFile(SourceFile *sourceFile, bool forceRefresh){ if (m_curSourceFile == sourceFile && !forceRefresh) return; sourceFile->ref(); m_sourceDisplay->setSource(sourceFile); if (m_curSourceFile) m_curSourceFile->deref(); m_curSourceFile = sourceFile;}void KJSDebugWin::setSourceLine(int sourceId, int lineno){ SourceFragment *source = m_sourceFragments[sourceId]; if (!source) return; SourceFile *sourceFile = source->sourceFile; if (m_curSourceFile != source->sourceFile) { for (int i = 0; i < m_sourceSel->count(); i++) if (m_sourceSelFiles.at(i) == sourceFile) m_sourceSel->setCurrentItem(i); displaySourceFile(sourceFile,false); } m_sourceDisplay->setCurrentLine(source->baseLine+lineno-2);}void KJSDebugWin::setNextSourceInfo(QString url, int baseLine){ m_nextSourceUrl = url; m_nextSourceBaseLine = baseLine;}void KJSDebugWin::sourceChanged(Interpreter *interpreter, QString url){ SourceFile *sourceFile = getSourceFile(interpreter,url); if (sourceFile && m_curSourceFile == sourceFile) displaySourceFile(sourceFile,true);}void KJSDebugWin::clearInterpreter(Interpreter *interpreter){ QMap<int,SourceFragment*>::Iterator it; for (it = m_sourceFragments.begin(); it != m_sourceFragments.end(); ++it) if (it.data() && it.data()->sourceFile->interpreter == interpreter) it.data()->sourceFile->interpreter = 0;}SourceFile *KJSDebugWin::getSourceFile(Interpreter *interpreter, QString url){ QString key = QString("%1|%2").arg((long)interpreter).arg(url); return m_sourceFiles[key];}void KJSDebugWin::setSourceFile(Interpreter *interpreter, QString url, SourceFile *sourceFile){ QString key = QString("%1|%2").arg((long)interpreter).arg(url); sourceFile->ref(); if (SourceFile* oldFile = m_sourceFiles[key]) oldFile->deref(); m_sourceFiles[key] = sourceFile;}void KJSDebugWin::removeSourceFile(Interpreter *interpreter, QString url){ QString key = QString("%1|%2").arg((long)interpreter).arg(url); if (SourceFile* oldFile = m_sourceFiles[key]) oldFile->deref(); m_sourceFiles.remove(key);}void KJSDebugWin::checkBreak(ExecState *exec){ if (m_breakpointCount > 0) { Context ctx = m_execs[m_execsCount-1]->context(); if (haveBreakpoint(ctx.sourceId(),ctx.curStmtFirstLine(),ctx.curStmtLastLine())) { m_mode = Next; m_steppingDepth = m_execsCount-1; } } if ((m_mode == Step || m_mode == Next) && m_steppingDepth == m_execsCount-1) enterSession(exec);}void KJSDebugWin::enterSession(ExecState *exec){ // This "enters" a new debugging session, i.e. enables usage of the debugging window // It re-enters the qt event loop here, allowing execution of other parts of the // program to continue while the script is stopped. We have to be a bit careful here, // i.e. make sure the user can't quit the app, and disable other event handlers which // could interfere with the debugging session. if (!isVisible()) show(); m_mode = Continue; if (m_execStates.isEmpty()) { disableOtherWindows(); m_nextAction->setEnabled(true); m_stepAction->setEnabled(true); m_continueAction->setEnabled(true); m_stopAction->setEnabled(true); m_breakAction->setEnabled(false); } m_execStates.push(exec); updateContextList(); qApp->enter_loop(); // won't return until leaveSession() is called}void KJSDebugWin::leaveSession(){ // Disables debugging for this window and returns to execute the rest of the script // (or aborts execution, if the user pressed stop). When this returns, the program // will exit the qt event loop, i.e. return to whatever processing was being done // before the debugger was stopped. assert(!m_execStates.isEmpty()); m_execStates.pop(); if (m_execStates.isEmpty()) { m_nextAction->setEnabled(false); m_stepAction->setEnabled(false); m_continueAction->setEnabled(false); m_stopAction->setEnabled(false); m_breakAction->setEnabled(true); m_sourceDisplay->setCurrentLine(-1); enableOtherWindows(); } qApp->exit_loop();}void KJSDebugWin::updateContextList(){ disconnect(m_contextList,SIGNAL(highlighted(int)),this,SLOT(slotShowFrame(int))); m_contextList->clear(); for (int i = 0; i < m_execsCount; i++) m_contextList->insertItem(contextStr(m_execs[i]->context())); if (m_execsCount > 0) { m_contextList->setSelected(m_execsCount-1, true); Context ctx = m_execs[m_execsCount-1]->context(); setSourceLine(ctx.sourceId(),ctx.curStmtFirstLine()); } connect(m_contextList,SIGNAL(highlighted(int)),this,SLOT(slotShowFrame(int)));}QString KJSDebugWin::contextStr(const Context &ctx){ QString str = ""; SourceFragment *sourceFragment = m_sourceFragments[ctx.sourceId()]; QString url = sourceFragment->sourceFile->url; int fileLineno = sourceFragment->baseLine+ctx.curStmtFirstLine()-1; switch (ctx.codeType()) { case GlobalCode: str = QString("Global code at %1:%2").arg(url).arg(fileLineno); break; case EvalCode: str = QString("Eval code at %1:%2").arg(url).arg(fileLineno); break; case FunctionCode: if (!ctx.functionName().isNull()) str = QString("%1() at %2:%3").arg(ctx.functionName().qstring()).arg(url).arg(fileLineno); else str = QString("Anonymous function at %1:%2").arg(url).arg(fileLineno); break; } return str;}bool KJSDebugWin::setBreakpoint(int sourceId, int lineno){ if (haveBreakpoint(sourceId,lineno,lineno)) return false; m_breakpointCount++; m_breakpoints = static_cast<Breakpoint*>(realloc(m_breakpoints, m_breakpointCount*sizeof(Breakpoint))); m_breakpoints[m_breakpointCount-1].sourceId = sourceId; m_breakpoints[m_breakpointCount-1].lineno = lineno; return true;}bool KJSDebugWin::deleteBreakpoint(int sourceId, int lineno){ for (int i = 0; i < m_breakpointCount; i++) { if (m_breakpoints[i].sourceId == sourceId && m_breakpoints[i].lineno == lineno) { memmove(m_breakpoints+i,m_breakpoints+i+1,(m_breakpointCount-i-1)*sizeof(Breakpoint)); m_breakpointCount--; m_breakpoints = static_cast<Breakpoint*>(realloc(m_breakpoints, m_breakpointCount*sizeof(Breakpoint))); return true; } } return false;}bool KJSDebugWin::haveBreakpoint(SourceFile *sourceFile, int line0, int line1){ for (int i = 0; i < m_breakpointCount; i++) { int sourceId = m_breakpoints[i].sourceId; int lineno = m_breakpoints[i].lineno; if (m_sourceFragments.contains(sourceId) && m_sourceFragments[sourceId]->sourceFile == sourceFile) { int absLineno = m_sourceFragments[sourceId]->baseLine+lineno-1; if (absLineno >= line0 && absLineno <= line1) return true; } } return false;}#include "kjs_debugwin.moc"#endif // KJS_DEBUGGER
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -