Chromium Code Reviews| 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..99b23d1df0e686470eaa3ea74c2b781fe307452c 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"; |
| @@ -98,6 +99,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 missing 'line' or 'line' < 0."; |
|
dgozman
2016/03/07 17:26:14
Can't be missing anymore.
kozy
2016/03/08 02:33:21
Done.
|
| + return false; |
| + } |
| + if (position->getColumn() < 0) { |
| + if (error) |
| + *error = "Position missing 'column' or '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 +278,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 +342,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 +590,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()) |
| + |
| + Vector<std::pair<int, int>> emptyPositions; |
|
dgozman
2016/03/07 17:26:14
Unused.
kozy
2016/03/08 02:33:21
Done.
|
| + const protocol::Vector<std::pair<int, int>>* ranges = nullptr; |
| + |
| + V8DebuggerScript& script = *(it->second); |
| + auto itBlackboxHash = m_scriptToBlackboxPositions.find(script.hasSourceURL() ? script.url() : script.hash()); |
| + if (itBlackboxHash != m_scriptToBlackboxPositions.end()) { |
| + ranges = itBlackboxHash->second; |
| + } else { |
| + if (script.hasSourceURL() && !m_blackboxRegexpPattern.isEmpty() && matches(m_debugger, script.sourceURL(), m_blackboxRegexpPattern, true)) { |
| + m_scriptToBlackboxPositions.set(script.sourceURL(), protocol::Vector<std::pair<int, int>>(1)); |
|
dgozman
2016/03/07 17:26:14
What is this Vector(1)? Not at all understandable.
kozy
2016/03/08 02:33:20
Done.
|
| + 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 +1287,55 @@ 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() ? hash : url, positions); |
|
dgozman
2016/03/07 17:26:14
Won't url and hash collide?
kozy
2016/03/08 02:33:21
Yes, they can collide.
Added a prefix to each entr
|
| } |
| - 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) |
|
dgozman
2016/03/07 17:26:14
Should remove from m_state as well.
kozy
2016/03/08 02:33:20
Done.
|
| +{ |
| + m_blackboxRegexpPattern = String(); |
| + m_scriptToBlackboxPositions.clear(); |
| } |
| void V8DebuggerAgentImpl::willExecuteScript(int scriptId) |
| @@ -1354,7 +1436,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,18 +1446,20 @@ 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>& sourceMapURLParam = sourceMapURL; |
| + const Maybe<String>& hashParam = hash; |
| const bool* isContentScriptParam = isContentScript ? &isContentScript : nullptr; |
| const bool* isInternalScriptParam = isInternalScript ? &isInternalScript : nullptr; |
| const bool* isLiveEditParam = isLiveEdit ? &isLiveEdit : nullptr; |
| 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, hashParam, isContentScriptParam, isInternalScriptParam, isLiveEditParam, 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, hashParam, isContentScriptParam, isInternalScriptParam, sourceMapURLParam, hasSourceURLParam, deprecatedCommentWasUsedParam); |
| m_scripts.set(parsedScript.scriptId, script); |
| @@ -1550,7 +1635,9 @@ void V8DebuggerAgentImpl::reset() |
| { |
| m_scheduledDebuggerStep = NoStep; |
| m_scripts.clear(); |
| - m_blackboxedPositions.clear(); |
| + |
| + m_scriptToBlackboxPositions.clear(); |
|
dgozman
2016/03/07 17:26:14
Forgot to |m_blackboxRegexpPattern = String()|
kozy
2016/03/08 02:33:21
Done.
|
| + |
| m_breakpointIdToDebuggerBreakpointIds.clear(); |
| resetAsyncCallTracker(); |
| m_promiseTracker->clear(); |