2 * Copyright (C) 2010 Apple Inc. All rights reserved.
3 * Copyright (C) 2013 Google Inc. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
15 * its contributors may be used to endorse or promote products derived
16 * from this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include "core/inspector/InspectorDebuggerAgent.h"
32 #include "core/inspector/JavaScriptCallFrame.h"
34 #include "bindings/v8/ScriptDebugServer.h"
35 #include "bindings/v8/ScriptObject.h"
36 #include "bindings/v8/ScriptRegexp.h"
37 #include "bindings/v8/ScriptSourceCode.h"
38 #include "core/dom/Document.h"
39 #include "core/fetch/Resource.h"
40 #include "core/inspector/ContentSearchUtils.h"
41 #include "core/inspector/InjectedScriptManager.h"
42 #include "core/inspector/InspectorPageAgent.h"
43 #include "core/inspector/InspectorState.h"
44 #include "core/inspector/InstrumentingAgents.h"
45 #include "core/inspector/ScriptArguments.h"
46 #include "core/inspector/ScriptCallStack.h"
47 #include "platform/JSONValues.h"
48 #include "wtf/text/WTFString.h"
50 using WebCore::TypeBuilder::Array;
51 using WebCore::TypeBuilder::Debugger::BreakpointId;
52 using WebCore::TypeBuilder::Debugger::CallFrame;
53 using WebCore::TypeBuilder::Debugger::FunctionDetails;
54 using WebCore::TypeBuilder::Debugger::ScriptId;
55 using WebCore::TypeBuilder::Debugger::StackTrace;
56 using WebCore::TypeBuilder::Runtime::RemoteObject;
60 namespace DebuggerAgentState {
61 static const char debuggerEnabled[] = "debuggerEnabled";
62 static const char javaScriptBreakpoints[] = "javaScriptBreakopints";
63 static const char pauseOnExceptionsState[] = "pauseOnExceptionsState";
64 static const char asyncCallStackDepth[] = "asyncCallStackDepth";
66 // Breakpoint properties.
67 static const char url[] = "url";
68 static const char isRegex[] = "isRegex";
69 static const char lineNumber[] = "lineNumber";
70 static const char columnNumber[] = "columnNumber";
71 static const char condition[] = "condition";
72 static const char isAnti[] = "isAnti";
73 static const char skipStackPattern[] = "skipStackPattern";
74 static const char skipAllPauses[] = "skipAllPauses";
75 static const char skipAllPausesExpiresOnReload[] = "skipAllPausesExpiresOnReload";
79 static const int numberOfStepsBeforeStepOut = 20;
81 const char InspectorDebuggerAgent::backtraceObjectGroup[] = "backtrace";
83 static String breakpointIdSuffix(InspectorDebuggerAgent::BreakpointSource source)
86 case InspectorDebuggerAgent::UserBreakpointSource:
88 case InspectorDebuggerAgent::DebugCommandBreakpointSource:
90 case InspectorDebuggerAgent::MonitorCommandBreakpointSource:
96 static String generateBreakpointId(const String& scriptId, int lineNumber, int columnNumber, InspectorDebuggerAgent::BreakpointSource source)
98 return scriptId + ':' + String::number(lineNumber) + ':' + String::number(columnNumber) + breakpointIdSuffix(source);
101 InspectorDebuggerAgent::InspectorDebuggerAgent(InjectedScriptManager* injectedScriptManager)
102 : InspectorBaseAgent<InspectorDebuggerAgent>("Debugger")
103 , m_injectedScriptManager(injectedScriptManager)
105 , m_pausedScriptState(nullptr)
106 , m_javaScriptPauseScheduled(false)
108 , m_skipStepInCount(numberOfStepsBeforeStepOut)
109 , m_skipAllPauses(false)
113 InspectorDebuggerAgent::~InspectorDebuggerAgent()
115 ASSERT(!m_instrumentingAgents->inspectorDebuggerAgent());
118 void InspectorDebuggerAgent::init()
120 // FIXME: make breakReason optional so that there was no need to init it with "other".
122 m_state->setLong(DebuggerAgentState::pauseOnExceptionsState, ScriptDebugServer::DontPauseOnExceptions);
125 void InspectorDebuggerAgent::enable()
127 m_instrumentingAgents->setInspectorDebuggerAgent(this);
129 // FIXME(WK44513): breakpoints activated flag should be synchronized between all front-ends
130 scriptDebugServer().setBreakpointsActivated(true);
131 startListeningScriptDebugServer();
134 m_listener->debuggerWasEnabled();
137 void InspectorDebuggerAgent::disable()
139 m_state->setObject(DebuggerAgentState::javaScriptBreakpoints, JSONObject::create());
140 m_state->setLong(DebuggerAgentState::pauseOnExceptionsState, ScriptDebugServer::DontPauseOnExceptions);
141 m_state->setString(DebuggerAgentState::skipStackPattern, "");
142 m_state->setLong(DebuggerAgentState::asyncCallStackDepth, 0);
143 m_instrumentingAgents->setInspectorDebuggerAgent(0);
145 stopListeningScriptDebugServer();
146 scriptDebugServer().clearBreakpoints();
147 scriptDebugServer().clearCompiledScripts();
151 m_listener->debuggerWasDisabled();
153 m_skipAllPauses = false;
156 bool InspectorDebuggerAgent::enabled()
158 return m_state->getBoolean(DebuggerAgentState::debuggerEnabled);
161 void InspectorDebuggerAgent::enable(ErrorString*)
167 m_state->setBoolean(DebuggerAgentState::debuggerEnabled, true);
172 void InspectorDebuggerAgent::disable(ErrorString*)
178 m_state->setBoolean(DebuggerAgentState::debuggerEnabled, false);
181 static PassOwnPtr<ScriptRegexp> compileSkipCallFramePattern(String patternText)
183 if (patternText.isEmpty())
185 OwnPtr<ScriptRegexp> result = adoptPtr(new ScriptRegexp(patternText, TextCaseSensitive));
186 if (!result->isValid())
188 return result.release();
191 void InspectorDebuggerAgent::restore()
194 m_frontend->globalObjectCleared();
196 long pauseState = m_state->getLong(DebuggerAgentState::pauseOnExceptionsState);
198 setPauseOnExceptionsImpl(&error, pauseState);
199 m_cachedSkipStackRegExp = compileSkipCallFramePattern(m_state->getString(DebuggerAgentState::skipStackPattern));
200 m_skipAllPauses = m_state->getBoolean(DebuggerAgentState::skipAllPauses);
201 if (m_skipAllPauses && m_state->getBoolean(DebuggerAgentState::skipAllPausesExpiresOnReload)) {
202 m_skipAllPauses = false;
203 m_state->setBoolean(DebuggerAgentState::skipAllPauses, false);
205 m_asyncCallStackTracker.setAsyncCallStackDepth(m_state->getLong(DebuggerAgentState::asyncCallStackDepth));
209 void InspectorDebuggerAgent::setFrontend(InspectorFrontend* frontend)
211 m_frontend = frontend->debugger();
214 void InspectorDebuggerAgent::clearFrontend()
223 // FIXME: due to m_state->mute() hack in InspectorController, debuggerEnabled is actually set to false only
224 // in InspectorState, but not in cookie. That's why after navigation debuggerEnabled will be true,
225 // but after front-end re-open it will still be false.
226 m_state->setBoolean(DebuggerAgentState::debuggerEnabled, false);
229 void InspectorDebuggerAgent::setBreakpointsActive(ErrorString*, bool active)
231 scriptDebugServer().setBreakpointsActivated(active);
234 void InspectorDebuggerAgent::setSkipAllPauses(ErrorString*, bool skipped, const bool* untilReload)
236 m_skipAllPauses = skipped;
237 bool untilReloadValue = untilReload && *untilReload;
238 m_state->setBoolean(DebuggerAgentState::skipAllPauses, m_skipAllPauses);
239 m_state->setBoolean(DebuggerAgentState::skipAllPausesExpiresOnReload, untilReloadValue);
242 void InspectorDebuggerAgent::pageDidCommitLoad()
244 if (m_state->getBoolean(DebuggerAgentState::skipAllPausesExpiresOnReload)) {
245 m_skipAllPauses = false;
246 m_state->setBoolean(DebuggerAgentState::skipAllPauses, m_skipAllPauses);
250 bool InspectorDebuggerAgent::isPaused()
252 return scriptDebugServer().isPaused();
255 bool InspectorDebuggerAgent::runningNestedMessageLoop()
257 return scriptDebugServer().runningNestedMessageLoop();
260 void InspectorDebuggerAgent::addMessageToConsole(MessageSource source, MessageType type)
262 if (source == ConsoleAPIMessageSource && type == AssertMessageType && scriptDebugServer().pauseOnExceptionsState() != ScriptDebugServer::DontPauseOnExceptions)
263 breakProgram(InspectorFrontend::Debugger::Reason::Assert, nullptr);
266 void InspectorDebuggerAgent::addMessageToConsole(MessageSource source, MessageType type, MessageLevel, const String&, ScriptCallStack*, unsigned long)
268 addMessageToConsole(source, type);
271 void InspectorDebuggerAgent::addMessageToConsole(MessageSource source, MessageType type, MessageLevel, const String&, ScriptState*, ScriptArguments*, unsigned long)
273 addMessageToConsole(source, type);
276 String InspectorDebuggerAgent::preprocessEventListener(LocalFrame* frame, const String& source, const String& url, const String& functionName)
278 return scriptDebugServer().preprocessEventListener(frame, source, url, functionName);
281 PassOwnPtr<ScriptSourceCode> InspectorDebuggerAgent::preprocess(LocalFrame* frame, const ScriptSourceCode& sourceCode)
283 return scriptDebugServer().preprocess(frame, sourceCode);
286 static PassRefPtr<JSONObject> buildObjectForBreakpointCookie(const String& url, int lineNumber, int columnNumber, const String& condition, bool isRegex, bool isAnti)
288 RefPtr<JSONObject> breakpointObject = JSONObject::create();
289 breakpointObject->setString(DebuggerAgentState::url, url);
290 breakpointObject->setNumber(DebuggerAgentState::lineNumber, lineNumber);
291 breakpointObject->setNumber(DebuggerAgentState::columnNumber, columnNumber);
292 breakpointObject->setString(DebuggerAgentState::condition, condition);
293 breakpointObject->setBoolean(DebuggerAgentState::isRegex, isRegex);
294 breakpointObject->setBoolean(DebuggerAgentState::isAnti, isAnti);
295 return breakpointObject;
298 static bool matches(const String& url, const String& pattern, bool isRegex)
301 ScriptRegexp regex(pattern, TextCaseSensitive);
302 return regex.match(url) != -1;
304 return url == pattern;
307 void InspectorDebuggerAgent::setBreakpointByUrl(ErrorString* errorString, int lineNumber, const String* const optionalURL, const String* const optionalURLRegex, const int* const optionalColumnNumber, const String* const optionalCondition, const bool* isAntiBreakpoint, BreakpointId* outBreakpointId, RefPtr<Array<TypeBuilder::Debugger::Location> >& locations)
309 locations = Array<TypeBuilder::Debugger::Location>::create();
310 if (!optionalURL == !optionalURLRegex) {
311 *errorString = "Either url or urlRegex must be specified.";
315 bool isAntiBreakpointValue = isAntiBreakpoint && *isAntiBreakpoint;
317 String url = optionalURL ? *optionalURL : *optionalURLRegex;
319 if (optionalColumnNumber) {
320 columnNumber = *optionalColumnNumber;
321 if (columnNumber < 0) {
322 *errorString = "Incorrect column number";
326 columnNumber = isAntiBreakpointValue ? -1 : 0;
328 String condition = optionalCondition ? *optionalCondition : "";
329 bool isRegex = optionalURLRegex;
331 String breakpointId = (isRegex ? "/" + url + "/" : url) + ':' + String::number(lineNumber) + ':' + String::number(columnNumber);
332 RefPtr<JSONObject> breakpointsCookie = m_state->getObject(DebuggerAgentState::javaScriptBreakpoints);
333 if (breakpointsCookie->find(breakpointId) != breakpointsCookie->end()) {
334 *errorString = "Breakpoint at specified location already exists.";
338 breakpointsCookie->setObject(breakpointId, buildObjectForBreakpointCookie(url, lineNumber, columnNumber, condition, isRegex, isAntiBreakpointValue));
339 m_state->setObject(DebuggerAgentState::javaScriptBreakpoints, breakpointsCookie);
341 if (!isAntiBreakpointValue) {
342 ScriptBreakpoint breakpoint(lineNumber, columnNumber, condition);
343 for (ScriptsMap::iterator it = m_scripts.begin(); it != m_scripts.end(); ++it) {
344 if (!matches(it->value.url, url, isRegex))
346 RefPtr<TypeBuilder::Debugger::Location> location = resolveBreakpoint(breakpointId, it->key, breakpoint, UserBreakpointSource);
348 locations->addItem(location);
351 *outBreakpointId = breakpointId;
354 static bool parseLocation(ErrorString* errorString, PassRefPtr<JSONObject> location, String* scriptId, int* lineNumber, int* columnNumber)
356 if (!location->getString("scriptId", scriptId) || !location->getNumber("lineNumber", lineNumber)) {
357 // FIXME: replace with input validation.
358 *errorString = "scriptId and lineNumber are required.";
362 location->getNumber("columnNumber", columnNumber);
366 void InspectorDebuggerAgent::setBreakpoint(ErrorString* errorString, const RefPtr<JSONObject>& location, const String* const optionalCondition, BreakpointId* outBreakpointId, RefPtr<TypeBuilder::Debugger::Location>& actualLocation)
372 if (!parseLocation(errorString, location, &scriptId, &lineNumber, &columnNumber))
375 String condition = optionalCondition ? *optionalCondition : emptyString();
377 String breakpointId = generateBreakpointId(scriptId, lineNumber, columnNumber, UserBreakpointSource);
378 if (m_breakpointIdToDebugServerBreakpointIds.find(breakpointId) != m_breakpointIdToDebugServerBreakpointIds.end()) {
379 *errorString = "Breakpoint at specified location already exists.";
382 ScriptBreakpoint breakpoint(lineNumber, columnNumber, condition);
383 actualLocation = resolveBreakpoint(breakpointId, scriptId, breakpoint, UserBreakpointSource);
385 *outBreakpointId = breakpointId;
387 *errorString = "Could not resolve breakpoint";
390 void InspectorDebuggerAgent::removeBreakpoint(ErrorString*, const String& breakpointId)
392 RefPtr<JSONObject> breakpointsCookie = m_state->getObject(DebuggerAgentState::javaScriptBreakpoints);
393 JSONObject::iterator it = breakpointsCookie->find(breakpointId);
394 bool isAntibreakpoint = false;
395 if (it != breakpointsCookie->end()) {
396 RefPtr<JSONObject> breakpointObject = it->value->asObject();
397 breakpointObject->getBoolean(DebuggerAgentState::isAnti, &isAntibreakpoint);
398 breakpointsCookie->remove(breakpointId);
399 m_state->setObject(DebuggerAgentState::javaScriptBreakpoints, breakpointsCookie);
402 if (!isAntibreakpoint)
403 removeBreakpoint(breakpointId);
406 void InspectorDebuggerAgent::removeBreakpoint(const String& breakpointId)
408 BreakpointIdToDebugServerBreakpointIdsMap::iterator debugServerBreakpointIdsIterator = m_breakpointIdToDebugServerBreakpointIds.find(breakpointId);
409 if (debugServerBreakpointIdsIterator == m_breakpointIdToDebugServerBreakpointIds.end())
411 for (size_t i = 0; i < debugServerBreakpointIdsIterator->value.size(); ++i) {
412 const String& debugServerBreakpointId = debugServerBreakpointIdsIterator->value[i];
413 scriptDebugServer().removeBreakpoint(debugServerBreakpointId);
414 m_serverBreakpoints.remove(debugServerBreakpointId);
416 m_breakpointIdToDebugServerBreakpointIds.remove(debugServerBreakpointIdsIterator);
419 void InspectorDebuggerAgent::continueToLocation(ErrorString* errorString, const RefPtr<JSONObject>& location, const bool* interstateLocationOpt)
421 bool interstateLocation = interstateLocationOpt ? *interstateLocationOpt : false;
422 if (!m_continueToLocationBreakpointId.isEmpty()) {
423 scriptDebugServer().removeBreakpoint(m_continueToLocationBreakpointId);
424 m_continueToLocationBreakpointId = "";
431 if (!parseLocation(errorString, location, &scriptId, &lineNumber, &columnNumber))
434 ScriptBreakpoint breakpoint(lineNumber, columnNumber, "");
435 m_continueToLocationBreakpointId = scriptDebugServer().setBreakpoint(scriptId, breakpoint, &lineNumber, &columnNumber, interstateLocation);
439 void InspectorDebuggerAgent::getStepInPositions(ErrorString* errorString, const String& callFrameId, RefPtr<Array<TypeBuilder::Debugger::Location> >& positions)
441 if (!isPaused() || m_currentCallStack.isEmpty()) {
442 *errorString = "Attempt to access callframe when debugger is not on pause";
445 InjectedScript injectedScript = m_injectedScriptManager->injectedScriptForObjectId(callFrameId);
446 if (injectedScript.isEmpty()) {
447 *errorString = "Inspected frame has gone";
451 injectedScript.getStepInPositions(errorString, m_currentCallStack, callFrameId, positions);
454 void InspectorDebuggerAgent::getBacktrace(ErrorString* errorString, RefPtr<Array<CallFrame> >& callFrames, RefPtr<StackTrace>& asyncStackTrace)
456 if (!assertPaused(errorString))
458 m_currentCallStack = scriptDebugServer().currentCallFrames();
459 callFrames = currentCallFrames();
460 asyncStackTrace = currentAsyncStackTrace();
463 String InspectorDebuggerAgent::scriptURL(JavaScriptCallFrame* frame)
465 String scriptIdString = String::number(frame->sourceID());
466 ScriptsMap::iterator it = m_scripts.find(scriptIdString);
467 if (it == m_scripts.end())
469 return it->value.url;
472 ScriptDebugListener::SkipPauseRequest InspectorDebuggerAgent::shouldSkipExceptionPause(RefPtr<JavaScriptCallFrame>& topFrame)
475 return ScriptDebugListener::Continue;
477 return ScriptDebugListener::NoSkip;
479 String topFrameScriptUrl = scriptURL(topFrame.get());
480 if (m_cachedSkipStackRegExp && !topFrameScriptUrl.isEmpty() && m_cachedSkipStackRegExp->match(topFrameScriptUrl) != -1)
481 return ScriptDebugListener::Continue;
483 // Match against breakpoints.
484 if (topFrameScriptUrl.isEmpty())
485 return ScriptDebugListener::NoSkip;
487 // Prepare top frame parameters.
488 int topFrameLineNumber = topFrame->line();
489 int topFrameColumnNumber = topFrame->column();
491 RefPtr<JSONObject> breakpointsCookie = m_state->getObject(DebuggerAgentState::javaScriptBreakpoints);
492 for (JSONObject::iterator it = breakpointsCookie->begin(); it != breakpointsCookie->end(); ++it) {
493 RefPtr<JSONObject> breakpointObject = it->value->asObject();
494 bool isAntibreakpoint;
495 breakpointObject->getBoolean(DebuggerAgentState::isAnti, &isAntibreakpoint);
496 if (!isAntibreakpoint)
500 breakpointObject->getNumber(DebuggerAgentState::lineNumber, &breakLineNumber);
501 int breakColumnNumber;
502 breakpointObject->getNumber(DebuggerAgentState::columnNumber, &breakColumnNumber);
504 if (breakLineNumber != topFrameLineNumber)
507 if (breakColumnNumber != -1 && breakColumnNumber != topFrameColumnNumber)
511 breakpointObject->getBoolean(DebuggerAgentState::isRegex, &isRegex);
513 breakpointObject->getString(DebuggerAgentState::url, &url);
514 if (!matches(topFrameScriptUrl, url, isRegex))
517 return ScriptDebugListener::Continue;
520 return ScriptDebugListener::NoSkip;
523 ScriptDebugListener::SkipPauseRequest InspectorDebuggerAgent::shouldSkipBreakpointPause(RefPtr<JavaScriptCallFrame>& topFrame)
526 return ScriptDebugListener::Continue;
528 return ScriptDebugListener::NoSkip;
529 return ScriptDebugListener::NoSkip;
532 ScriptDebugListener::SkipPauseRequest InspectorDebuggerAgent::shouldSkipStepPause(RefPtr<JavaScriptCallFrame>& topFrame)
535 return ScriptDebugListener::Continue;
537 return ScriptDebugListener::NoSkip;
539 if (m_cachedSkipStackRegExp) {
540 String scriptUrl = scriptURL(topFrame.get());
541 if (!scriptUrl.isEmpty() && m_cachedSkipStackRegExp->match(scriptUrl) != -1) {
542 if (m_skipStepInCount > 0) {
544 return ScriptDebugListener::StepInto;
546 return ScriptDebugListener::StepOut;
549 return ScriptDebugListener::NoSkip;
552 PassRefPtr<TypeBuilder::Debugger::Location> InspectorDebuggerAgent::resolveBreakpoint(const String& breakpointId, const String& scriptId, const ScriptBreakpoint& breakpoint, BreakpointSource source)
554 ScriptsMap::iterator scriptIterator = m_scripts.find(scriptId);
555 if (scriptIterator == m_scripts.end())
557 Script& script = scriptIterator->value;
558 if (breakpoint.lineNumber < script.startLine || script.endLine < breakpoint.lineNumber)
561 int actualLineNumber;
562 int actualColumnNumber;
563 String debugServerBreakpointId = scriptDebugServer().setBreakpoint(scriptId, breakpoint, &actualLineNumber, &actualColumnNumber, false);
564 if (debugServerBreakpointId.isEmpty())
567 m_serverBreakpoints.set(debugServerBreakpointId, std::make_pair(breakpointId, source));
569 BreakpointIdToDebugServerBreakpointIdsMap::iterator debugServerBreakpointIdsIterator = m_breakpointIdToDebugServerBreakpointIds.find(breakpointId);
570 if (debugServerBreakpointIdsIterator == m_breakpointIdToDebugServerBreakpointIds.end())
571 m_breakpointIdToDebugServerBreakpointIds.set(breakpointId, Vector<String>()).storedValue->value.append(debugServerBreakpointId);
573 debugServerBreakpointIdsIterator->value.append(debugServerBreakpointId);
575 RefPtr<TypeBuilder::Debugger::Location> location = TypeBuilder::Debugger::Location::create()
576 .setScriptId(scriptId)
577 .setLineNumber(actualLineNumber);
578 location->setColumnNumber(actualColumnNumber);
582 void InspectorDebuggerAgent::searchInContent(ErrorString* error, const String& scriptId, const String& query, const bool* const optionalCaseSensitive, const bool* const optionalIsRegex, RefPtr<Array<WebCore::TypeBuilder::Page::SearchMatch> >& results)
584 bool isRegex = optionalIsRegex ? *optionalIsRegex : false;
585 bool caseSensitive = optionalCaseSensitive ? *optionalCaseSensitive : false;
587 ScriptsMap::iterator it = m_scripts.find(scriptId);
588 if (it != m_scripts.end())
589 results = ContentSearchUtils::searchInTextByLines(it->value.source, query, caseSensitive, isRegex);
591 *error = "No script for id: " + scriptId;
594 void InspectorDebuggerAgent::setScriptSource(ErrorString* error, RefPtr<TypeBuilder::Debugger::SetScriptSourceError>& errorData, const String& scriptId, const String& newContent, const bool* const preview, RefPtr<Array<CallFrame> >& newCallFrames, RefPtr<JSONObject>& result, RefPtr<StackTrace>& asyncStackTrace)
596 bool previewOnly = preview && *preview;
597 if (!scriptDebugServer().setScriptSource(scriptId, newContent, previewOnly, error, errorData, &m_currentCallStack, &result))
599 newCallFrames = currentCallFrames();
600 asyncStackTrace = currentAsyncStackTrace();
603 void InspectorDebuggerAgent::restartFrame(ErrorString* errorString, const String& callFrameId, RefPtr<Array<CallFrame> >& newCallFrames, RefPtr<JSONObject>& result, RefPtr<StackTrace>& asyncStackTrace)
605 if (!isPaused() || m_currentCallStack.isEmpty()) {
606 *errorString = "Attempt to access callframe when debugger is not on pause";
609 InjectedScript injectedScript = m_injectedScriptManager->injectedScriptForObjectId(callFrameId);
610 if (injectedScript.isEmpty()) {
611 *errorString = "Inspected frame has gone";
615 injectedScript.restartFrame(errorString, m_currentCallStack, callFrameId, &result);
616 m_currentCallStack = scriptDebugServer().currentCallFrames();
617 newCallFrames = currentCallFrames();
618 asyncStackTrace = currentAsyncStackTrace();
621 void InspectorDebuggerAgent::getScriptSource(ErrorString* error, const String& scriptId, String* scriptSource)
623 ScriptsMap::iterator it = m_scripts.find(scriptId);
624 if (it != m_scripts.end())
625 *scriptSource = it->value.source;
627 *error = "No script for id: " + scriptId;
630 void InspectorDebuggerAgent::getFunctionDetails(ErrorString* errorString, const String& functionId, RefPtr<FunctionDetails>& details)
632 InjectedScript injectedScript = m_injectedScriptManager->injectedScriptForObjectId(functionId);
633 if (injectedScript.isEmpty()) {
634 *errorString = "Function object id is obsolete";
637 injectedScript.getFunctionDetails(errorString, functionId, &details);
640 void InspectorDebuggerAgent::schedulePauseOnNextStatement(InspectorFrontend::Debugger::Reason::Enum breakReason, PassRefPtr<JSONObject> data)
642 if (m_javaScriptPauseScheduled)
644 m_breakReason = breakReason;
645 m_breakAuxData = data;
646 scriptDebugServer().setPauseOnNextStatement(true);
649 void InspectorDebuggerAgent::cancelPauseOnNextStatement()
651 if (m_javaScriptPauseScheduled)
654 scriptDebugServer().setPauseOnNextStatement(false);
657 void InspectorDebuggerAgent::didInstallTimer(ExecutionContext* context, int timerId, int timeout, bool singleShot)
659 if (m_asyncCallStackTracker.isEnabled())
660 m_asyncCallStackTracker.didInstallTimer(context, timerId, singleShot, scriptDebugServer().currentCallFramesForAsyncStack());
663 void InspectorDebuggerAgent::didRemoveTimer(ExecutionContext* context, int timerId)
665 if (m_asyncCallStackTracker.isEnabled())
666 m_asyncCallStackTracker.didRemoveTimer(context, timerId);
669 bool InspectorDebuggerAgent::willFireTimer(ExecutionContext* context, int timerId)
671 if (m_asyncCallStackTracker.isEnabled())
672 m_asyncCallStackTracker.willFireTimer(context, timerId);
676 void InspectorDebuggerAgent::didFireTimer()
678 if (m_asyncCallStackTracker.isEnabled())
679 m_asyncCallStackTracker.didFireAsyncCall();
680 cancelPauseOnNextStatement();
683 void InspectorDebuggerAgent::didRequestAnimationFrame(Document* document, int callbackId)
685 if (m_asyncCallStackTracker.isEnabled())
686 m_asyncCallStackTracker.didRequestAnimationFrame(document, callbackId, scriptDebugServer().currentCallFramesForAsyncStack());
689 void InspectorDebuggerAgent::didCancelAnimationFrame(Document* document, int callbackId)
691 if (m_asyncCallStackTracker.isEnabled())
692 m_asyncCallStackTracker.didCancelAnimationFrame(document, callbackId);
695 bool InspectorDebuggerAgent::willFireAnimationFrame(Document* document, int callbackId)
697 if (m_asyncCallStackTracker.isEnabled())
698 m_asyncCallStackTracker.willFireAnimationFrame(document, callbackId);
702 void InspectorDebuggerAgent::didFireAnimationFrame()
704 if (m_asyncCallStackTracker.isEnabled())
705 m_asyncCallStackTracker.didFireAsyncCall();
708 void InspectorDebuggerAgent::didAddEventListener(EventTarget* eventTarget, const AtomicString& eventType, EventListener* listener, bool useCapture)
710 if (m_asyncCallStackTracker.isEnabled())
711 m_asyncCallStackTracker.didAddEventListener(eventTarget, eventType, listener, useCapture, scriptDebugServer().currentCallFramesForAsyncStack());
714 void InspectorDebuggerAgent::didRemoveEventListener(EventTarget* eventTarget, const AtomicString& eventType, EventListener* listener, bool useCapture)
716 if (m_asyncCallStackTracker.isEnabled())
717 m_asyncCallStackTracker.didRemoveEventListener(eventTarget, eventType, listener, useCapture);
720 void InspectorDebuggerAgent::didRemoveAllEventListeners(EventTarget* eventTarget)
722 if (m_asyncCallStackTracker.isEnabled())
723 m_asyncCallStackTracker.didRemoveAllEventListeners(eventTarget);
726 void InspectorDebuggerAgent::willHandleEvent(EventTarget* eventTarget, const AtomicString& eventType, EventListener* listener, bool useCapture)
728 if (m_asyncCallStackTracker.isEnabled())
729 m_asyncCallStackTracker.willHandleEvent(eventTarget, eventType, listener, useCapture);
732 void InspectorDebuggerAgent::didHandleEvent()
734 if (m_asyncCallStackTracker.isEnabled())
735 m_asyncCallStackTracker.didFireAsyncCall();
736 cancelPauseOnNextStatement();
739 void InspectorDebuggerAgent::willLoadXHR(XMLHttpRequest* xhr, ThreadableLoaderClient*, const AtomicString&, const KURL&, bool async, FormData*, const HTTPHeaderMap&, bool)
741 if (m_asyncCallStackTracker.isEnabled() && async)
742 m_asyncCallStackTracker.willLoadXHR(xhr, scriptDebugServer().currentCallFramesForAsyncStack());
745 void InspectorDebuggerAgent::didEnqueueMutationRecord(ExecutionContext* context, MutationObserver* observer)
747 if (m_asyncCallStackTracker.isEnabled() && !m_asyncCallStackTracker.hasEnqueuedMutationRecord(context, observer))
748 m_asyncCallStackTracker.didEnqueueMutationRecord(context, observer, scriptDebugServer().currentCallFramesForAsyncStack());
751 void InspectorDebuggerAgent::didClearAllMutationRecords(ExecutionContext* context, MutationObserver* observer)
753 if (m_asyncCallStackTracker.isEnabled())
754 m_asyncCallStackTracker.didClearAllMutationRecords(context, observer);
757 void InspectorDebuggerAgent::willDeliverMutationRecords(ExecutionContext* context, MutationObserver* observer)
759 if (m_asyncCallStackTracker.isEnabled())
760 m_asyncCallStackTracker.willDeliverMutationRecords(context, observer);
763 void InspectorDebuggerAgent::didDeliverMutationRecords()
765 if (m_asyncCallStackTracker.isEnabled())
766 m_asyncCallStackTracker.didFireAsyncCall();
769 void InspectorDebuggerAgent::didPostPromiseTask(ExecutionContext* context, ExecutionContextTask* task, bool isResolved)
771 if (m_asyncCallStackTracker.isEnabled())
772 m_asyncCallStackTracker.didPostPromiseTask(context, task, isResolved, scriptDebugServer().currentCallFramesForAsyncStack());
775 void InspectorDebuggerAgent::willPerformPromiseTask(ExecutionContext* context, ExecutionContextTask* task)
777 if (m_asyncCallStackTracker.isEnabled())
778 m_asyncCallStackTracker.willPerformPromiseTask(context, task);
781 void InspectorDebuggerAgent::didPerformPromiseTask()
783 if (m_asyncCallStackTracker.isEnabled())
784 m_asyncCallStackTracker.didFireAsyncCall();
787 bool InspectorDebuggerAgent::isPromiseTrackerEnabled()
789 return m_promiseTracker.isEnabled();
792 void InspectorDebuggerAgent::didCreatePromise(const ScriptObject& promise)
794 if (m_promiseTracker.isEnabled())
795 m_promiseTracker.didCreatePromise(promise);
798 void InspectorDebuggerAgent::didUpdatePromiseParent(const ScriptObject& promise, const ScriptObject& parentPromise)
800 if (m_promiseTracker.isEnabled())
801 m_promiseTracker.didUpdatePromiseParent(promise, parentPromise);
804 void InspectorDebuggerAgent::didUpdatePromiseState(const ScriptObject& promise, V8PromiseCustom::PromiseState state, const ScriptValue& result)
806 if (m_promiseTracker.isEnabled())
807 m_promiseTracker.didUpdatePromiseState(promise, state, result);
810 void InspectorDebuggerAgent::pause(ErrorString*)
812 if (m_javaScriptPauseScheduled)
815 scriptDebugServer().setPauseOnNextStatement(true);
816 m_javaScriptPauseScheduled = true;
819 void InspectorDebuggerAgent::resume(ErrorString* errorString)
821 if (!assertPaused(errorString))
823 m_injectedScriptManager->releaseObjectGroup(InspectorDebuggerAgent::backtraceObjectGroup);
824 scriptDebugServer().continueProgram();
827 ScriptValue InspectorDebuggerAgent::resolveCallFrame(ErrorString* errorString, const String* callFrameId)
830 return ScriptValue();
831 if (!isPaused() || m_currentCallStack.isEmpty()) {
832 *errorString = "Attempt to access callframe when debugger is not on pause";
833 return ScriptValue();
835 InjectedScript injectedScript = m_injectedScriptManager->injectedScriptForObjectId(*callFrameId);
836 if (injectedScript.isEmpty()) {
837 *errorString = "Inspected frame has gone";
838 return ScriptValue();
840 return injectedScript.findCallFrameById(errorString, m_currentCallStack, *callFrameId);
843 void InspectorDebuggerAgent::stepOver(ErrorString* errorString, const String* callFrameId)
845 if (!assertPaused(errorString))
847 ScriptValue frame = resolveCallFrame(errorString, callFrameId);
848 if (!errorString->isEmpty())
850 m_injectedScriptManager->releaseObjectGroup(InspectorDebuggerAgent::backtraceObjectGroup);
851 scriptDebugServer().stepOverStatement(frame);
854 void InspectorDebuggerAgent::stepInto(ErrorString* errorString)
856 if (!assertPaused(errorString))
858 m_injectedScriptManager->releaseObjectGroup(InspectorDebuggerAgent::backtraceObjectGroup);
859 scriptDebugServer().stepIntoStatement();
861 m_listener->stepInto();
864 void InspectorDebuggerAgent::stepOut(ErrorString* errorString, const String* callFrameId)
866 if (!assertPaused(errorString))
868 ScriptValue frame = resolveCallFrame(errorString, callFrameId);
869 if (!errorString->isEmpty())
871 m_injectedScriptManager->releaseObjectGroup(InspectorDebuggerAgent::backtraceObjectGroup);
872 scriptDebugServer().stepOutOfFunction(frame);
875 void InspectorDebuggerAgent::setPauseOnExceptions(ErrorString* errorString, const String& stringPauseState)
877 ScriptDebugServer::PauseOnExceptionsState pauseState;
878 if (stringPauseState == "none")
879 pauseState = ScriptDebugServer::DontPauseOnExceptions;
880 else if (stringPauseState == "all")
881 pauseState = ScriptDebugServer::PauseOnAllExceptions;
882 else if (stringPauseState == "uncaught")
883 pauseState = ScriptDebugServer::PauseOnUncaughtExceptions;
885 *errorString = "Unknown pause on exceptions mode: " + stringPauseState;
888 setPauseOnExceptionsImpl(errorString, pauseState);
891 void InspectorDebuggerAgent::setPauseOnExceptionsImpl(ErrorString* errorString, int pauseState)
893 scriptDebugServer().setPauseOnExceptionsState(static_cast<ScriptDebugServer::PauseOnExceptionsState>(pauseState));
894 if (scriptDebugServer().pauseOnExceptionsState() != pauseState)
895 *errorString = "Internal error. Could not change pause on exceptions state";
897 m_state->setLong(DebuggerAgentState::pauseOnExceptionsState, pauseState);
900 void InspectorDebuggerAgent::evaluateOnCallFrame(ErrorString* errorString, const String& callFrameId, const String& expression, const String* const objectGroup, const bool* const includeCommandLineAPI, const bool* const doNotPauseOnExceptionsAndMuteConsole, const bool* const returnByValue, const bool* generatePreview, RefPtr<RemoteObject>& result, TypeBuilder::OptOutput<bool>* wasThrown)
902 if (!isPaused() || m_currentCallStack.isEmpty()) {
903 *errorString = "Attempt to access callframe when debugger is not on pause";
906 InjectedScript injectedScript = m_injectedScriptManager->injectedScriptForObjectId(callFrameId);
907 if (injectedScript.isEmpty()) {
908 *errorString = "Inspected frame has gone";
912 ScriptDebugServer::PauseOnExceptionsState previousPauseOnExceptionsState = scriptDebugServer().pauseOnExceptionsState();
913 if (doNotPauseOnExceptionsAndMuteConsole ? *doNotPauseOnExceptionsAndMuteConsole : false) {
914 if (previousPauseOnExceptionsState != ScriptDebugServer::DontPauseOnExceptions)
915 scriptDebugServer().setPauseOnExceptionsState(ScriptDebugServer::DontPauseOnExceptions);
919 Vector<ScriptValue> asyncCallStacks;
920 const AsyncCallStackTracker::AsyncCallChain* asyncChain = m_asyncCallStackTracker.isEnabled() ? m_asyncCallStackTracker.currentAsyncCallChain() : 0;
922 const AsyncCallStackTracker::AsyncCallStackVector& callStacks = asyncChain->callStacks();
923 asyncCallStacks.resize(callStacks.size());
924 AsyncCallStackTracker::AsyncCallStackVector::const_iterator it = callStacks.begin();
925 for (size_t i = 0; it != callStacks.end(); ++it, ++i)
926 asyncCallStacks[i] = (*it)->callFrames();
929 injectedScript.evaluateOnCallFrame(errorString, m_currentCallStack, asyncCallStacks, callFrameId, expression, objectGroup ? *objectGroup : "", includeCommandLineAPI ? *includeCommandLineAPI : false, returnByValue ? *returnByValue : false, generatePreview ? *generatePreview : false, &result, wasThrown);
931 if (doNotPauseOnExceptionsAndMuteConsole ? *doNotPauseOnExceptionsAndMuteConsole : false) {
933 if (scriptDebugServer().pauseOnExceptionsState() != previousPauseOnExceptionsState)
934 scriptDebugServer().setPauseOnExceptionsState(previousPauseOnExceptionsState);
938 void InspectorDebuggerAgent::compileScript(ErrorString* errorString, const String& expression, const String& sourceURL, const int* executionContextId, TypeBuilder::OptOutput<ScriptId>* scriptId, TypeBuilder::OptOutput<String>* syntaxErrorMessage)
940 InjectedScript injectedScript = injectedScriptForEval(errorString, executionContextId);
941 if (injectedScript.isEmpty()) {
942 *errorString = "Inspected frame has gone";
946 String scriptIdValue;
947 String exceptionMessage;
948 scriptDebugServer().compileScript(injectedScript.scriptState(), expression, sourceURL, &scriptIdValue, &exceptionMessage);
949 if (!scriptIdValue && !exceptionMessage) {
950 *errorString = "Script compilation failed";
953 *syntaxErrorMessage = exceptionMessage;
954 *scriptId = scriptIdValue;
957 void InspectorDebuggerAgent::runScript(ErrorString* errorString, const ScriptId& scriptId, const int* executionContextId, const String* const objectGroup, const bool* const doNotPauseOnExceptionsAndMuteConsole, RefPtr<RemoteObject>& result, TypeBuilder::OptOutput<bool>* wasThrown)
959 InjectedScript injectedScript = injectedScriptForEval(errorString, executionContextId);
960 if (injectedScript.isEmpty()) {
961 *errorString = "Inspected frame has gone";
965 ScriptDebugServer::PauseOnExceptionsState previousPauseOnExceptionsState = scriptDebugServer().pauseOnExceptionsState();
966 if (doNotPauseOnExceptionsAndMuteConsole && *doNotPauseOnExceptionsAndMuteConsole) {
967 if (previousPauseOnExceptionsState != ScriptDebugServer::DontPauseOnExceptions)
968 scriptDebugServer().setPauseOnExceptionsState(ScriptDebugServer::DontPauseOnExceptions);
974 String exceptionMessage;
975 scriptDebugServer().runScript(injectedScript.scriptState(), scriptId, &value, &wasThrownValue, &exceptionMessage);
976 *wasThrown = wasThrownValue;
977 if (value.isEmpty()) {
978 *errorString = "Script execution failed";
981 result = injectedScript.wrapObject(value, objectGroup ? *objectGroup : "");
983 result->setDescription(exceptionMessage);
985 if (doNotPauseOnExceptionsAndMuteConsole && *doNotPauseOnExceptionsAndMuteConsole) {
987 if (scriptDebugServer().pauseOnExceptionsState() != previousPauseOnExceptionsState)
988 scriptDebugServer().setPauseOnExceptionsState(previousPauseOnExceptionsState);
992 void InspectorDebuggerAgent::setOverlayMessage(ErrorString*, const String*)
996 void InspectorDebuggerAgent::setVariableValue(ErrorString* errorString, int scopeNumber, const String& variableName, const RefPtr<JSONObject>& newValue, const String* callFrameId, const String* functionObjectId)
998 InjectedScript injectedScript;
1000 if (!isPaused() || m_currentCallStack.isEmpty()) {
1001 *errorString = "Attempt to access callframe when debugger is not on pause";
1004 injectedScript = m_injectedScriptManager->injectedScriptForObjectId(*callFrameId);
1005 if (injectedScript.isEmpty()) {
1006 *errorString = "Inspected frame has gone";
1009 } else if (functionObjectId) {
1010 injectedScript = m_injectedScriptManager->injectedScriptForObjectId(*functionObjectId);
1011 if (injectedScript.isEmpty()) {
1012 *errorString = "Function object id cannot be resolved";
1016 *errorString = "Either call frame or function object must be specified";
1019 String newValueString = newValue->toJSONString();
1021 injectedScript.setVariableValue(errorString, m_currentCallStack, callFrameId, functionObjectId, scopeNumber, variableName, newValueString);
1024 void InspectorDebuggerAgent::skipStackFrames(ErrorString* errorString, const String* pattern)
1026 OwnPtr<ScriptRegexp> compiled;
1027 String patternValue = pattern ? *pattern : "";
1028 if (!patternValue.isEmpty()) {
1029 compiled = compileSkipCallFramePattern(patternValue);
1031 *errorString = "Invalid regular expression";
1035 m_state->setString(DebuggerAgentState::skipStackPattern, patternValue);
1036 m_cachedSkipStackRegExp = compiled.release();
1039 void InspectorDebuggerAgent::setAsyncCallStackDepth(ErrorString*, int depth)
1041 m_state->setLong(DebuggerAgentState::asyncCallStackDepth, depth);
1042 m_asyncCallStackTracker.setAsyncCallStackDepth(depth);
1045 void InspectorDebuggerAgent::scriptExecutionBlockedByCSP(const String& directiveText)
1047 if (scriptDebugServer().pauseOnExceptionsState() != ScriptDebugServer::DontPauseOnExceptions) {
1048 RefPtr<JSONObject> directive = JSONObject::create();
1049 directive->setString("directiveText", directiveText);
1050 breakProgram(InspectorFrontend::Debugger::Reason::CSPViolation, directive.release());
1054 PassRefPtr<Array<CallFrame> > InspectorDebuggerAgent::currentCallFrames()
1056 if (!m_pausedScriptState || m_currentCallStack.isEmpty())
1057 return Array<CallFrame>::create();
1058 InjectedScript injectedScript = m_injectedScriptManager->injectedScriptFor(m_pausedScriptState.get());
1059 if (injectedScript.isEmpty()) {
1060 ASSERT_NOT_REACHED();
1061 return Array<CallFrame>::create();
1063 return injectedScript.wrapCallFrames(m_currentCallStack, 0);
1066 PassRefPtr<StackTrace> InspectorDebuggerAgent::currentAsyncStackTrace()
1068 if (!m_pausedScriptState || !m_asyncCallStackTracker.isEnabled())
1070 InjectedScript injectedScript = m_injectedScriptManager->injectedScriptFor(m_pausedScriptState.get());
1071 if (injectedScript.isEmpty()) {
1072 ASSERT_NOT_REACHED();
1075 const AsyncCallStackTracker::AsyncCallChain* chain = m_asyncCallStackTracker.currentAsyncCallChain();
1078 const AsyncCallStackTracker::AsyncCallStackVector& callStacks = chain->callStacks();
1079 if (callStacks.isEmpty())
1081 RefPtr<StackTrace> result;
1082 int asyncOrdinal = callStacks.size();
1083 for (AsyncCallStackTracker::AsyncCallStackVector::const_reverse_iterator it = callStacks.rbegin(); it != callStacks.rend(); ++it) {
1084 RefPtr<StackTrace> next = StackTrace::create()
1085 .setCallFrames(injectedScript.wrapCallFrames((*it)->callFrames(), asyncOrdinal--))
1087 next->setDescription((*it)->description());
1089 next->setAsyncStackTrace(result.release());
1092 return result.release();
1095 String InspectorDebuggerAgent::sourceMapURLForScript(const Script& script)
1098 String sourceMapURL = ContentSearchUtils::findSourceMapURL(script.source, ContentSearchUtils::JavaScriptMagicComment, &deprecated);
1099 if (!sourceMapURL.isEmpty()) {
1100 // FIXME: add deprecated console message here.
1101 return sourceMapURL;
1104 if (script.url.isEmpty())
1107 InspectorPageAgent* pageAgent = m_instrumentingAgents->inspectorPageAgent();
1110 return pageAgent->resourceSourceMapURL(script.url);
1113 // JavaScriptDebugListener functions
1115 void InspectorDebuggerAgent::didParseSource(const String& scriptId, const Script& script)
1117 // Don't send script content to the front end until it's really needed.
1118 const bool* isContentScript = script.isContentScript ? &script.isContentScript : 0;
1119 String sourceMapURL = sourceMapURLForScript(script);
1120 String* sourceMapURLParam = sourceMapURL.isNull() ? 0 : &sourceMapURL;
1122 if (!script.startLine && !script.startColumn) {
1124 sourceURL = ContentSearchUtils::findSourceURL(script.source, ContentSearchUtils::JavaScriptMagicComment, &deprecated);
1125 // FIXME: add deprecated console message here.
1127 bool hasSourceURL = !sourceURL.isEmpty();
1128 String scriptURL = hasSourceURL ? sourceURL : script.url;
1129 bool* hasSourceURLParam = hasSourceURL ? &hasSourceURL : 0;
1130 m_frontend->scriptParsed(scriptId, scriptURL, script.startLine, script.startColumn, script.endLine, script.endColumn, isContentScript, sourceMapURLParam, hasSourceURLParam);
1132 m_scripts.set(scriptId, script);
1134 if (scriptURL.isEmpty())
1137 RefPtr<JSONObject> breakpointsCookie = m_state->getObject(DebuggerAgentState::javaScriptBreakpoints);
1138 for (JSONObject::iterator it = breakpointsCookie->begin(); it != breakpointsCookie->end(); ++it) {
1139 RefPtr<JSONObject> breakpointObject = it->value->asObject();
1140 bool isAntibreakpoint;
1141 breakpointObject->getBoolean(DebuggerAgentState::isAnti, &isAntibreakpoint);
1142 if (isAntibreakpoint)
1145 breakpointObject->getBoolean(DebuggerAgentState::isRegex, &isRegex);
1147 breakpointObject->getString(DebuggerAgentState::url, &url);
1148 if (!matches(scriptURL, url, isRegex))
1150 ScriptBreakpoint breakpoint;
1151 breakpointObject->getNumber(DebuggerAgentState::lineNumber, &breakpoint.lineNumber);
1152 breakpointObject->getNumber(DebuggerAgentState::columnNumber, &breakpoint.columnNumber);
1153 breakpointObject->getString(DebuggerAgentState::condition, &breakpoint.condition);
1154 RefPtr<TypeBuilder::Debugger::Location> location = resolveBreakpoint(it->key, scriptId, breakpoint, UserBreakpointSource);
1156 m_frontend->breakpointResolved(it->key, location);
1160 void InspectorDebuggerAgent::failedToParseSource(const String& url, const String& data, int firstLine, int errorLine, const String& errorMessage)
1162 m_frontend->scriptFailedToParse(url, data, firstLine, errorLine, errorMessage);
1165 void InspectorDebuggerAgent::didPause(ScriptState* scriptState, const ScriptValue& callFrames, const ScriptValue& exception, const Vector<String>& hitBreakpoints)
1167 ASSERT(scriptState && !m_pausedScriptState);
1168 m_pausedScriptState = scriptState;
1169 m_currentCallStack = callFrames;
1171 m_skipStepInCount = numberOfStepsBeforeStepOut;
1173 if (!exception.isEmpty()) {
1174 InjectedScript injectedScript = m_injectedScriptManager->injectedScriptFor(scriptState);
1175 if (!injectedScript.isEmpty()) {
1176 m_breakReason = InspectorFrontend::Debugger::Reason::Exception;
1177 m_breakAuxData = injectedScript.wrapObject(exception, InspectorDebuggerAgent::backtraceObjectGroup)->openAccessors();
1178 // m_breakAuxData might be null after this.
1182 RefPtr<Array<String> > hitBreakpointIds = Array<String>::create();
1184 for (Vector<String>::const_iterator i = hitBreakpoints.begin(); i != hitBreakpoints.end(); ++i) {
1185 DebugServerBreakpointToBreakpointIdAndSourceMap::iterator breakpointIterator = m_serverBreakpoints.find(*i);
1186 if (breakpointIterator != m_serverBreakpoints.end()) {
1187 const String& localId = breakpointIterator->value.first;
1188 hitBreakpointIds->addItem(localId);
1190 BreakpointSource source = breakpointIterator->value.second;
1191 if (m_breakReason == InspectorFrontend::Debugger::Reason::Other && source == DebugCommandBreakpointSource)
1192 m_breakReason = InspectorFrontend::Debugger::Reason::DebugCommand;
1196 m_frontend->paused(currentCallFrames(), m_breakReason, m_breakAuxData, hitBreakpointIds, currentAsyncStackTrace());
1197 m_javaScriptPauseScheduled = false;
1199 if (!m_continueToLocationBreakpointId.isEmpty()) {
1200 scriptDebugServer().removeBreakpoint(m_continueToLocationBreakpointId);
1201 m_continueToLocationBreakpointId = "";
1204 m_listener->didPause();
1207 void InspectorDebuggerAgent::didContinue()
1209 m_pausedScriptState = nullptr;
1210 m_currentCallStack = ScriptValue();
1211 clearBreakDetails();
1212 m_frontend->resumed();
1215 bool InspectorDebuggerAgent::canBreakProgram()
1217 return scriptDebugServer().canBreakProgram();
1220 void InspectorDebuggerAgent::breakProgram(InspectorFrontend::Debugger::Reason::Enum breakReason, PassRefPtr<JSONObject> data)
1222 if (m_skipAllPauses)
1224 m_breakReason = breakReason;
1225 m_breakAuxData = data;
1226 scriptDebugServer().breakProgram();
1229 void InspectorDebuggerAgent::clear()
1231 m_pausedScriptState = nullptr;
1232 m_currentCallStack = ScriptValue();
1234 m_breakpointIdToDebugServerBreakpointIds.clear();
1235 m_asyncCallStackTracker.clear();
1236 m_promiseTracker.clear();
1237 m_continueToLocationBreakpointId = String();
1238 clearBreakDetails();
1239 m_javaScriptPauseScheduled = false;
1241 setOverlayMessage(&error, 0);
1244 bool InspectorDebuggerAgent::assertPaused(ErrorString* errorString)
1246 if (!m_pausedScriptState) {
1247 *errorString = "Can only perform operation while paused.";
1253 void InspectorDebuggerAgent::clearBreakDetails()
1255 m_breakReason = InspectorFrontend::Debugger::Reason::Other;
1256 m_breakAuxData = nullptr;
1259 void InspectorDebuggerAgent::setBreakpoint(const String& scriptId, int lineNumber, int columnNumber, BreakpointSource source, const String& condition)
1261 String breakpointId = generateBreakpointId(scriptId, lineNumber, columnNumber, source);
1262 ScriptBreakpoint breakpoint(lineNumber, columnNumber, condition);
1263 resolveBreakpoint(breakpointId, scriptId, breakpoint, source);
1266 void InspectorDebuggerAgent::removeBreakpoint(const String& scriptId, int lineNumber, int columnNumber, BreakpointSource source)
1268 removeBreakpoint(generateBreakpointId(scriptId, lineNumber, columnNumber, source));
1271 void InspectorDebuggerAgent::reset()
1274 m_breakpointIdToDebugServerBreakpointIds.clear();
1275 m_asyncCallStackTracker.clear();
1276 m_promiseTracker.clear();
1278 m_frontend->globalObjectCleared();
1281 } // namespace WebCore