bool Debugger::hasBreakpoint(SourceID sourceID, const TextPosition& position, Breakpoint *hitBreakpoint) { if (!m_breakpointsActivated) return false; SourceIDToBreakpointsMap::const_iterator it = m_sourceIDToBreakpoints.find(sourceID); if (it == m_sourceIDToBreakpoints.end()) return false; unsigned line = position.m_line.zeroBasedInt(); unsigned column = position.m_column.zeroBasedInt(); LineToBreakpointsMap::const_iterator breaksIt = it->value.find(line); if (breaksIt == it->value.end()) return false; bool hit = false; const BreakpointsInLine& breakpoints = breaksIt->value; unsigned breakpointsCount = breakpoints.size(); unsigned i; for (i = 0; i < breakpointsCount; i++) { unsigned breakLine = breakpoints[i].line; unsigned breakColumn = breakpoints[i].column; // Since frontend truncates the indent, the first statement in a line must match the breakpoint (line,0). ASSERT(this == m_currentCallFrame->codeBlock()->globalObject()->debugger()); if ((line != m_lastExecutedLine && line == breakLine && !breakColumn) || (line == breakLine && column == breakColumn)) { hit = true; break; } } if (!hit) return false; if (hitBreakpoint) *hitBreakpoint = breakpoints[i]; if (breakpoints[i].condition.isEmpty()) return true; // We cannot stop in the debugger while executing condition code, // so make it looks like the debugger is already paused. TemporaryPausedState pausedState(*this); JSValue exception; DebuggerCallFrame* debuggerCallFrame = currentDebuggerCallFrame(); JSValue result = debuggerCallFrame->evaluate(breakpoints[i].condition, exception); // We can lose the debugger while executing JavaScript. if (!m_currentCallFrame) return false; if (exception) { // An erroneous condition counts as "false". handleExceptionInBreakpointCondition(m_currentCallFrame, exception); return false; } return result.toBoolean(m_currentCallFrame); }
bool ScriptDebugServer::evaluateBreakpointAction(const ScriptBreakpointAction& breakpointAction) { DebuggerCallFrame* debuggerCallFrame = currentDebuggerCallFrame(); switch (breakpointAction.type) { case ScriptBreakpointActionTypeLog: { dispatchBreakpointActionLog(debuggerCallFrame->exec(), breakpointAction.data); break; } case ScriptBreakpointActionTypeEvaluate: { JSValue exception; debuggerCallFrame->evaluate(breakpointAction.data, exception); if (exception) reportException(debuggerCallFrame->exec(), exception); break; } case ScriptBreakpointActionTypeSound: dispatchBreakpointActionSound(debuggerCallFrame->exec()); break; case ScriptBreakpointActionTypeProbe: { JSValue exception; JSValue result = debuggerCallFrame->evaluate(breakpointAction.data, exception); if (exception) reportException(debuggerCallFrame->exec(), exception); JSC::ExecState* state = debuggerCallFrame->scope()->globalObject()->globalExec(); Deprecated::ScriptValue wrappedResult = Deprecated::ScriptValue(state->vm(), exception ? exception : result); dispatchDidSampleProbe(state, breakpointAction.identifier, wrappedResult); break; } default: ASSERT_NOT_REACHED(); } return true; }
bool ScriptDebugServer::evaluateBreakpointAction(const ScriptBreakpointAction& breakpointAction) const { DebuggerCallFrame* debuggerCallFrame = currentDebuggerCallFrame(); switch (breakpointAction.type) { case ScriptBreakpointActionTypeLog: { DOMWindow& window = asJSDOMWindow(debuggerCallFrame->dynamicGlobalObject())->impl(); if (PageConsole* console = window.pageConsole()) console->addMessage(JSMessageSource, LogMessageLevel, breakpointAction.data); break; } case ScriptBreakpointActionTypeEvaluate: { JSValue exception; debuggerCallFrame->evaluate(breakpointAction.data, exception); if (exception) reportException(debuggerCallFrame->exec(), exception); break; } case ScriptBreakpointActionTypeSound: systemBeep(); break; } return true; }