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..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(); |