Index: src/inspector/v8-debugger-agent-impl.cc |
diff --git a/src/inspector/v8-debugger-agent-impl.cc b/src/inspector/v8-debugger-agent-impl.cc |
index 664c2ed095a0545d2ee655c3b15178e21e056f3f..8cb20a220be7390909472818accf80b015f33bc0 100644 |
--- a/src/inspector/v8-debugger-agent-impl.cc |
+++ b/src/inspector/v8-debugger-agent-impl.cc |
@@ -50,6 +50,8 @@ static const char isRegex[] = "isRegex"; |
static const char lineNumber[] = "lineNumber"; |
static const char columnNumber[] = "columnNumber"; |
static const char condition[] = "condition"; |
+static const char sourceLineHint[] = "sourceLineHint"; |
+ |
static const char skipAllPauses[] = "skipAllPauses"; |
} // namespace DebuggerAgentState |
@@ -58,6 +60,8 @@ static const char kBacktraceObjectGroup[] = "backtrace"; |
static const char kDebuggerNotEnabled[] = "Debugger agent is not enabled"; |
static const char kDebuggerNotPaused[] = |
"Can only perform operation while paused."; |
+static const int kSourceLineHintToCheck = 32; |
+static const int kSourceLineHintMaxLength = 128; |
namespace { |
@@ -241,13 +245,15 @@ Response V8DebuggerAgentImpl::setSkipAllPauses(bool skip) { |
static std::unique_ptr<protocol::DictionaryValue> |
buildObjectForBreakpointCookie(const String16& url, int lineNumber, |
int columnNumber, const String16& condition, |
- bool isRegex) { |
+ bool isRegex, const String16& sourceLineHint) { |
std::unique_ptr<protocol::DictionaryValue> breakpointObject = |
protocol::DictionaryValue::create(); |
breakpointObject->setString(DebuggerAgentState::url, url); |
breakpointObject->setInteger(DebuggerAgentState::lineNumber, lineNumber); |
breakpointObject->setInteger(DebuggerAgentState::columnNumber, columnNumber); |
breakpointObject->setString(DebuggerAgentState::condition, condition); |
+ breakpointObject->setString(DebuggerAgentState::sourceLineHint, |
+ sourceLineHint); |
breakpointObject->setBoolean(DebuggerAgentState::isRegex, isRegex); |
return breakpointObject; |
} |
@@ -295,20 +301,24 @@ Response V8DebuggerAgentImpl::setBreakpointByUrl( |
if (breakpointsCookie->get(breakpointId)) |
return Response::Error("Breakpoint at specified location already exists."); |
- breakpointsCookie->setObject( |
- breakpointId, buildObjectForBreakpointCookie( |
- url, lineNumber, columnNumber, condition, isRegex)); |
- |
ScriptBreakpoint breakpoint(String16(), lineNumber, columnNumber, condition); |
+ String16 sourceLineHint; |
for (const auto& script : m_scripts) { |
if (!matches(m_inspector, script.second->sourceURL(), url, isRegex)) |
continue; |
breakpoint.script_id = script.first; |
- std::unique_ptr<protocol::Debugger::Location> location = |
- resolveBreakpoint(breakpointId, breakpoint, UserBreakpointSource); |
+ sourceLineHint = |
+ script.second->lineAt(lineNumber, kSourceLineHintMaxLength); |
+ std::unique_ptr<protocol::Debugger::Location> location = resolveBreakpoint( |
+ breakpointId, breakpoint, UserBreakpointSource, String16()); |
if (location) (*locations)->addItem(std::move(location)); |
} |
+ breakpointsCookie->setObject( |
+ breakpointId, |
+ buildObjectForBreakpointCookie(url, lineNumber, columnNumber, condition, |
+ isRegex, sourceLineHint)); |
+ |
*outBreakpointId = breakpointId; |
return Response::OK(); |
} |
@@ -327,8 +337,8 @@ Response V8DebuggerAgentImpl::setBreakpoint( |
m_breakpointIdToDebuggerBreakpointIds.end()) { |
return Response::Error("Breakpoint at specified location already exists."); |
} |
- *actualLocation = |
- resolveBreakpoint(breakpointId, breakpoint, UserBreakpointSource); |
+ *actualLocation = resolveBreakpoint(breakpointId, breakpoint, |
+ UserBreakpointSource, String16()); |
if (!*actualLocation) return Response::Error("Could not resolve breakpoint"); |
*outBreakpointId = breakpointId; |
return Response::OK(); |
@@ -455,10 +465,30 @@ bool V8DebuggerAgentImpl::isFunctionBlackboxed(const String16& scriptId, |
std::distance(ranges.begin(), itStartRange) % 2; |
} |
+namespace { |
+bool checkLine(V8DebuggerScript* script, int lineNumber, const String16& hint) { |
+ if (lineNumber < script->startLine() || lineNumber > script->endLine()) |
+ return false; |
+ return script->lineAt(lineNumber, kSourceLineHintMaxLength) == hint; |
+} |
+ |
+int ajustLineNumber(V8DebuggerScript* script, int lineNumber, |
alph
2017/02/08 02:02:08
adjust
|
+ const String16& hint) { |
+ if (hint.isEmpty()) return lineNumber; |
+ if (checkLine(script, lineNumber, hint)) return lineNumber; |
+ for (int i = 1; i < kSourceLineHintToCheck / 2; ++i) { |
+ if (checkLine(script, lineNumber + i, hint)) return lineNumber + i; |
+ if (checkLine(script, lineNumber - i, hint)) return lineNumber - i; |
+ } |
+ return lineNumber; |
+} |
+} // namespace |
+ |
std::unique_ptr<protocol::Debugger::Location> |
V8DebuggerAgentImpl::resolveBreakpoint(const String16& breakpointId, |
const ScriptBreakpoint& breakpoint, |
- BreakpointSource source) { |
+ BreakpointSource source, |
+ const String16& sourceLineHint) { |
v8::HandleScope handles(m_isolate); |
DCHECK(enabled()); |
// FIXME: remove these checks once crbug.com/520702 is resolved. |
@@ -466,12 +496,17 @@ V8DebuggerAgentImpl::resolveBreakpoint(const String16& breakpointId, |
CHECK(!breakpoint.script_id.isEmpty()); |
ScriptsMap::iterator scriptIterator = m_scripts.find(breakpoint.script_id); |
if (scriptIterator == m_scripts.end()) return nullptr; |
- if (breakpoint.line_number < scriptIterator->second->startLine() || |
- scriptIterator->second->endLine() < breakpoint.line_number) |
+ |
+ V8DebuggerScript* script = scriptIterator->second.get(); |
+ ScriptBreakpoint translatedBreakpoint = breakpoint; |
+ translatedBreakpoint.line_number = |
+ ajustLineNumber(script, translatedBreakpoint.line_number, sourceLineHint); |
+ if (translatedBreakpoint.line_number < script->startLine() || |
+ script->endLine() < translatedBreakpoint.line_number) { |
return nullptr; |
+ } |
// Translate from protocol location to v8 location for the debugger. |
- ScriptBreakpoint translatedBreakpoint = breakpoint; |
m_debugger->wasmTranslation()->TranslateProtocolLocationToWasmScriptLocation( |
&translatedBreakpoint.script_id, &translatedBreakpoint.line_number, |
&translatedBreakpoint.column_number); |
@@ -506,7 +541,7 @@ Response V8DebuggerAgentImpl::searchInContent( |
return Response::Error("No script for id: " + scriptId); |
std::vector<std::unique_ptr<protocol::Debugger::SearchMatch>> matches = |
- searchInTextByLinesImpl(m_session, it->second->source(m_isolate), query, |
+ searchInTextByLinesImpl(m_session, it->second->source(), query, |
optionalCaseSensitive.fromMaybe(false), |
optionalIsRegex.fromMaybe(false)); |
*results = protocol::Array<protocol::Debugger::SearchMatch>::create(); |
@@ -585,7 +620,7 @@ Response V8DebuggerAgentImpl::getScriptSource(const String16& scriptId, |
if (it == m_scripts.end()) |
return Response::Error("No script for id: " + scriptId); |
v8::HandleScope handles(m_isolate); |
- *scriptSource = it->second->source(m_isolate); |
+ *scriptSource = it->second->source(); |
return Response::OK(); |
} |
@@ -979,7 +1014,7 @@ bool V8DebuggerAgentImpl::isPaused() const { return m_debugger->isPaused(); } |
void V8DebuggerAgentImpl::didParseSource( |
std::unique_ptr<V8DebuggerScript> script, bool success) { |
v8::HandleScope handles(m_isolate); |
- String16 scriptSource = script->source(m_isolate); |
+ String16 scriptSource = script->source(); |
if (!success) script->setSourceURL(findSourceURL(scriptSource, false)); |
if (!success) |
script->setSourceMappingURL(findSourceMapURL(scriptSource, false)); |
@@ -1022,14 +1057,14 @@ void V8DebuggerAgentImpl::didParseSource( |
m_frontend.scriptParsed( |
scriptId, scriptURL, scriptRef->startLine(), scriptRef->startColumn(), |
scriptRef->endLine(), scriptRef->endColumn(), contextId, |
- scriptRef->hash(m_isolate), std::move(executionContextAuxDataParam), |
+ scriptRef->hash(), std::move(executionContextAuxDataParam), |
isLiveEditParam, std::move(sourceMapURLParam), hasSourceURLParam, |
isModuleParam); |
else |
m_frontend.scriptFailedToParse( |
scriptId, scriptURL, scriptRef->startLine(), scriptRef->startColumn(), |
scriptRef->endLine(), scriptRef->endColumn(), contextId, |
- scriptRef->hash(m_isolate), std::move(executionContextAuxDataParam), |
+ scriptRef->hash(), std::move(executionContextAuxDataParam), |
std::move(sourceMapURLParam), hasSourceURLParam, isModuleParam); |
if (scriptURL.isEmpty() || !success) return; |
@@ -1045,6 +1080,7 @@ void V8DebuggerAgentImpl::didParseSource( |
bool isRegex; |
breakpointObject->getBoolean(DebuggerAgentState::isRegex, &isRegex); |
String16 url; |
+ String16 sourceLineHint; |
breakpointObject->getString(DebuggerAgentState::url, &url); |
if (!matches(m_inspector, scriptURL, url, isRegex)) continue; |
ScriptBreakpoint breakpoint; |
@@ -1055,8 +1091,10 @@ void V8DebuggerAgentImpl::didParseSource( |
&breakpoint.column_number); |
breakpointObject->getString(DebuggerAgentState::condition, |
&breakpoint.condition); |
- std::unique_ptr<protocol::Debugger::Location> location = |
- resolveBreakpoint(cookie.first, breakpoint, UserBreakpointSource); |
+ breakpointObject->getString(DebuggerAgentState::sourceLineHint, |
+ &sourceLineHint); |
+ std::unique_ptr<protocol::Debugger::Location> location = resolveBreakpoint( |
+ cookie.first, breakpoint, UserBreakpointSource, sourceLineHint); |
if (location) |
m_frontend.breakpointResolved(cookie.first, std::move(location)); |
} |
@@ -1163,7 +1201,7 @@ void V8DebuggerAgentImpl::setBreakpointAt(const String16& scriptId, |
const String16& condition) { |
ScriptBreakpoint breakpoint(scriptId, lineNumber, columnNumber, condition); |
String16 breakpointId = generateBreakpointId(breakpoint, source); |
- resolveBreakpoint(breakpointId, breakpoint, source); |
+ resolveBreakpoint(breakpointId, breakpoint, source, String16()); |
} |
void V8DebuggerAgentImpl::removeBreakpointAt(const String16& scriptId, |