Index: third_party/WebKit/Source/platform/v8_inspector/V8DebuggerAgentImpl.cpp |
diff --git a/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerAgentImpl.cpp b/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerAgentImpl.cpp |
index a4d5b2ef9bdcc1da9fd0b7bd11043cf6f5924235..1fee5f12cdf4f89dab8c782adbde39adafc6c70d 100644 |
--- a/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerAgentImpl.cpp |
+++ b/third_party/WebKit/Source/platform/v8_inspector/V8DebuggerAgentImpl.cpp |
@@ -46,6 +46,7 @@ static const char pauseOnExceptionsState[] = "pauseOnExceptionsState"; |
static const char asyncCallStackDepth[] = "asyncCallStackDepth"; |
static const char promiseTrackerEnabled[] = "promiseTrackerEnabled"; |
static const char promiseTrackerCaptureStacks[] = "promiseTrackerCaptureStacks"; |
+static const char blackboxState[] = "blackboxState"; |
// Breakpoint properties. |
static const char url[] = "url"; |
@@ -63,6 +64,9 @@ const char V8DebuggerAgent::backtraceObjectGroup[] = "backtrace"; |
const int V8DebuggerAgent::unknownAsyncOperationId = 0; |
+const char hashPrefix[] = "hash:"; |
+const char urlPrefix[] = "url:"; |
+ |
static String breakpointIdSuffix(V8DebuggerAgentImpl::BreakpointSource source) |
{ |
switch (source) { |
@@ -98,6 +102,43 @@ static void appendUnsignedAsHex(unsigned number, String& destination) |
} |
} |
+static bool parseBlackboxPositions(ErrorString* error, protocol::Array<protocol::Debugger::ScriptPosition>* inPositions, protocol::Vector<std::pair<int, int>>* outPositions) |
+{ |
+ if (!inPositions) { |
+ protocol::Vector<std::pair<int, int>> blackboxed(1); |
+ outPositions->swap(blackboxed); |
+ return true; |
+ } |
+ protocol::Vector<std::pair<int, int>> positions(inPositions->length()); |
+ for (size_t i = 0; i < positions.size(); ++i) { |
+ protocol::Debugger::ScriptPosition* position = inPositions->get(i); |
+ if (position->getLine() < 0) { |
+ if (error) |
+ *error = "Position 'line' < 0."; |
+ return false; |
+ } |
+ if (position->getColumn() < 0) { |
+ if (error) |
+ *error = "Position 'column' < 0."; |
+ return false; |
+ } |
+ positions[i] = std::make_pair(position->getLine(), position->getColumn()); |
+ } |
+ |
+ for (size_t i = 1; i < positions.size(); ++i) { |
+ if (positions[i - 1].first < positions[i].first) |
+ continue; |
+ if (positions[i - 1].first == positions[i].first && positions[i - 1].second < positions[i].second) |
+ continue; |
+ if (error) |
+ *error = "Input positions array is not sorted or contains duplicate values."; |
+ return false; |
+ } |
+ |
+ outPositions->swap(positions); |
+ return true; |
+} |
+ |
// Hash algorithm for substrings is described in "Über die Komplexität der Multiplikation in |
// eingeschränkten Branchingprogrammmodellen" by Woelfe. |
// http://opendatastructures.org/versions/edition-0.1d/ods-java/node33.html#SECTION00832000000000000000 |
@@ -240,7 +281,10 @@ void V8DebuggerAgentImpl::disable(ErrorString*) |
m_pausedContext.Reset(); |
m_currentCallStack.Reset(); |
m_scripts.clear(); |
- m_blackboxedPositions.clear(); |
+ |
+ m_scriptToBlackboxPositions.clear(); |
+ m_blackboxRegexpPattern = String(); |
+ |
m_breakpointIdToDebuggerBreakpointIds.clear(); |
internalSetAsyncCallStackDepth(0); |
m_promiseTracker->setEnabled(false, false); |
@@ -301,6 +345,22 @@ void V8DebuggerAgentImpl::restore() |
internalSetAsyncCallStackDepth(asyncCallStackDepth); |
m_promiseTracker->setEnabled(m_state->booleanProperty(DebuggerAgentState::promiseTrackerEnabled, false), m_state->booleanProperty(DebuggerAgentState::promiseTrackerCaptureStacks, false)); |
+ |
+ restoreBlackboxState(); |
+} |
+ |
+void V8DebuggerAgentImpl::restoreBlackboxState() |
+{ |
+ protocol::ListValue* patternsState = m_state->getArray(DebuggerAgentState::blackboxState); |
+ if (!patternsState) |
+ return; |
+ protocol::ErrorSupport errors; |
+ OwnPtr<protocol::Array<protocol::Debugger::BlackboxPattern>> patterns = protocol::Array<protocol::Debugger::BlackboxPattern>::parse(patternsState, &errors); |
+ ASSERT(!errors.hasErrors()); |
+ |
+ ErrorString error; |
+ addBlackboxPatterns(&error, patterns.release()); |
+ ASSERT(error.isEmpty()); |
} |
void V8DebuggerAgentImpl::setBreakpointsActive(ErrorString* errorString, bool active) |
@@ -533,16 +593,28 @@ bool V8DebuggerAgentImpl::isCallFrameWithUnknownScriptOrBlackboxed(JavaScriptCal |
{ |
if (!frame) |
return true; |
- ScriptsMap::iterator it = m_scripts.find(String::number(frame->sourceID())); |
+ String scriptId = String::number(frame->sourceID()); |
+ ScriptsMap::iterator it = m_scripts.find(scriptId); |
if (it == m_scripts.end()) { |
// Unknown scripts are blackboxed. |
return true; |
} |
- auto itBlackboxedPositions = m_blackboxedPositions.find(String::number(frame->sourceID())); |
- if (itBlackboxedPositions == m_blackboxedPositions.end()) |
+ |
+ const protocol::Vector<std::pair<int, int>>* ranges = nullptr; |
+ |
+ V8DebuggerScript& script = *(it->second); |
+ auto itBlackboxHash = m_scriptToBlackboxPositions.find(script.hasSourceURL() ? urlPrefix + script.url() : hashPrefix + script.hash()); |
dgozman
2016/03/08 18:48:12
I think it's not worth to add strings in this hot
|
+ if (itBlackboxHash != m_scriptToBlackboxPositions.end()) { |
+ ranges = itBlackboxHash->second; |
+ } else { |
+ if (!script.sourceURL().isEmpty() && !m_blackboxRegexpPattern.isEmpty() && matches(m_debugger, script.sourceURL(), m_blackboxRegexpPattern, true)) { |
+ protocol::Vector<std::pair<int, int>> blackboxedSourcePositions(1); |
dgozman
2016/03/08 18:48:12
Explicit.
|
+ m_scriptToBlackboxPositions.set(urlPrefix + script.sourceURL(), blackboxedSourcePositions); |
+ return true; |
+ } |
return false; |
+ } |
- protocol::Vector<std::pair<int, int>>* ranges = itBlackboxedPositions->second; |
auto itRange = std::lower_bound(ranges->begin(), ranges->end(), std::make_pair(frame->line(), frame->column()), positionComparator); |
// Ranges array contains positions in script where blackbox state is changed. |
// [(0,0) ... ranges[0]) isn't blackboxed, [ranges[0] ... ranges[1]) is blackboxed... |
@@ -1218,42 +1290,56 @@ void V8DebuggerAgentImpl::removeAsyncOperationBreakpoint(ErrorString* errorStrin |
m_asyncOperationBreakpoints.remove(operationId); |
} |
-void V8DebuggerAgentImpl::setBlackboxedRanges(ErrorString* error, const String& scriptId, PassOwnPtr<protocol::Array<protocol::Debugger::ScriptPosition>> inPositions) |
+void V8DebuggerAgentImpl::addBlackboxPatterns(ErrorString* error, PassOwnPtr<protocol::Array<protocol::Debugger::BlackboxPattern>> patterns) |
{ |
- if (!m_scripts.contains(scriptId)) { |
- *error = "No script with passed id."; |
- return; |
- } |
+ String blackboxRegexpPattern; |
+ protocol::HashMap<String, protocol::Vector<std::pair<int, int>>> scriptToBlackboxPositions; |
- if (!inPositions->length()) { |
- m_blackboxedPositions.remove(scriptId); |
- return; |
- } |
+ for (size_t i = 0; i < patterns->length(); ++i) { |
+ protocol::Debugger::BlackboxPattern* pattern = patterns->get(i); |
- protocol::Vector<std::pair<int, int>> positions(inPositions->length()); |
- for (size_t i = 0; i < positions.size(); ++i) { |
- protocol::Debugger::ScriptPosition* position = inPositions->get(i); |
- if (position->getLine() < 0) { |
- *error = "Position missing 'line' or 'line' < 0."; |
+ String url = pattern->getUrl(String()); |
+ String hash = pattern->getHash(String()); |
+ String regexp = pattern->getRegexp(String()); |
+ |
+ if (!url.isEmpty() + !hash.isEmpty() + !regexp.isEmpty() != 1) { |
+ *error = "Only one field should be set in BlackboxPattern: url or hash or regexp."; |
return; |
} |
- if (position->getColumn() < 0) { |
- *error = "Position missing 'column' or 'column' < 0."; |
+ |
+ if (pattern->hasPositions() && !regexp.isEmpty()) { |
+ *error = "Positions can't be used with regexp BlackboxPattern."; |
return; |
} |
- positions[i] = std::make_pair(position->getLine(), position->getColumn()); |
- } |
- for (size_t i = 1; i < positions.size(); ++i) { |
- if (positions[i - 1].first < positions[i].first) |
- continue; |
- if (positions[i - 1].first == positions[i].first && positions[i - 1].second < positions[i].second) |
- continue; |
- *error = "Input positions array is not sorted or contains duplicate values."; |
- return; |
+ protocol::Vector<std::pair<int, int>> positions; |
+ if (!parseBlackboxPositions(error, pattern->getPositions(nullptr), &positions)) |
+ return; |
+ |
+ if (!regexp.isEmpty()) |
+ blackboxRegexpPattern = blackboxRegexpPattern + (blackboxRegexpPattern.isEmpty() ? "" : "|") + regexp; |
+ else |
+ scriptToBlackboxPositions.set(url.isEmpty() ? hashPrefix + hash : urlPrefix + url, positions); |
} |
- m_blackboxedPositions.set(scriptId, positions); |
+ m_blackboxRegexpPattern = m_blackboxRegexpPattern + (m_blackboxRegexpPattern.isEmpty() ? "" : "|") + blackboxRegexpPattern; |
+ for (const auto& positions : scriptToBlackboxPositions) |
+ m_scriptToBlackboxPositions.set(positions.first, *positions.second); |
+ |
+ if (!m_state->getArray(DebuggerAgentState::blackboxState)) |
+ m_state->setArray(DebuggerAgentState::blackboxState, protocol::ListValue::create()); |
+ protocol::ListValue* currentPatterns = m_state->getArray(DebuggerAgentState::blackboxState); |
+ |
+ for (size_t i = 0; i < patterns->length(); ++i) |
+ currentPatterns->pushValue(patterns->get(i)->serialize()); |
+ return; |
+} |
+ |
+void V8DebuggerAgentImpl::clearBlackboxPatterns(ErrorString* error) |
+{ |
+ m_blackboxRegexpPattern = String(); |
+ m_scriptToBlackboxPositions.clear(); |
+ m_state->setArray(DebuggerAgentState::blackboxState, protocol::ListValue::create()); |
} |
void V8DebuggerAgentImpl::willExecuteScript(int scriptId) |
@@ -1354,7 +1440,8 @@ void V8DebuggerAgentImpl::didParseSource(const V8DebuggerParsedScript& parsedScr |
else if (!script.sourceMappingURL().isEmpty()) |
V8ContentSearchUtil::findSourceMapURL(script.source(), false, &isDeprecatedSourceMappingURL); |
- script.setHash(calculateHash(script.source())); |
+ if (!script.hasSourceURL()) |
+ script.setHash(calculateHash(script.source())); |
int executionContextId = script.executionContextId(); |
bool isContentScript = script.isContentScript(); |
@@ -1363,8 +1450,10 @@ void V8DebuggerAgentImpl::didParseSource(const V8DebuggerParsedScript& parsedScr |
bool hasSourceURL = script.hasSourceURL(); |
String scriptURL = script.sourceURL(); |
String sourceMapURL = script.sourceMappingURL(); |
+ String hash = script.hash(); |
bool deprecatedCommentWasUsed = isDeprecatedSourceURL || isDeprecatedSourceMappingURL; |
+ const Maybe<String>& hashParam = hash; |
const Maybe<String>& sourceMapURLParam = sourceMapURL; |
const bool* isContentScriptParam = isContentScript ? &isContentScript : nullptr; |
const bool* isInternalScriptParam = isInternalScript ? &isInternalScript : nullptr; |
@@ -1372,9 +1461,9 @@ void V8DebuggerAgentImpl::didParseSource(const V8DebuggerParsedScript& parsedScr |
const bool* hasSourceURLParam = hasSourceURL ? &hasSourceURL : nullptr; |
const bool* deprecatedCommentWasUsedParam = deprecatedCommentWasUsed ? &deprecatedCommentWasUsed : nullptr; |
if (parsedScript.success) |
- m_frontend->scriptParsed(parsedScript.scriptId, scriptURL, script.startLine(), script.startColumn(), script.endLine(), script.endColumn(), executionContextId, script.hash(), isContentScriptParam, isInternalScriptParam, isLiveEditParam, sourceMapURLParam, hasSourceURLParam, deprecatedCommentWasUsedParam); |
+ m_frontend->scriptParsed(parsedScript.scriptId, scriptURL, script.startLine(), script.startColumn(), script.endLine(), script.endColumn(), executionContextId, isContentScriptParam, isInternalScriptParam, isLiveEditParam, hashParam, sourceMapURLParam, hasSourceURLParam, deprecatedCommentWasUsedParam); |
else |
- m_frontend->scriptFailedToParse(parsedScript.scriptId, scriptURL, script.startLine(), script.startColumn(), script.endLine(), script.endColumn(), executionContextId, script.hash(), isContentScriptParam, isInternalScriptParam, sourceMapURLParam, hasSourceURLParam, deprecatedCommentWasUsedParam); |
+ m_frontend->scriptFailedToParse(parsedScript.scriptId, scriptURL, script.startLine(), script.startColumn(), script.endLine(), script.endColumn(), executionContextId, isContentScriptParam, isInternalScriptParam, hashParam, sourceMapURLParam, hasSourceURLParam, deprecatedCommentWasUsedParam); |
m_scripts.set(parsedScript.scriptId, script); |
@@ -1550,7 +1639,10 @@ void V8DebuggerAgentImpl::reset() |
{ |
m_scheduledDebuggerStep = NoStep; |
m_scripts.clear(); |
- m_blackboxedPositions.clear(); |
+ |
+ m_scriptToBlackboxPositions.clear(); |
+ m_blackboxRegexpPattern = String(); |
+ |
m_breakpointIdToDebuggerBreakpointIds.clear(); |
resetAsyncCallTracker(); |
m_promiseTracker->clear(); |