| OLD | NEW | 
|---|
|  | (Empty) | 
| 1 // Copyright 2016 the V8 project authors. All rights reserved. |  | 
| 2 // Use of this source code is governed by a BSD-style license that can be |  | 
| 3 // found in the LICENSE file. |  | 
| 4 |  | 
| 5 #include "src/inspector/SearchUtil.h" |  | 
| 6 |  | 
| 7 #include "src/inspector/V8InspectorImpl.h" |  | 
| 8 #include "src/inspector/V8InspectorSessionImpl.h" |  | 
| 9 #include "src/inspector/V8Regex.h" |  | 
| 10 #include "src/inspector/protocol/Protocol.h" |  | 
| 11 |  | 
| 12 namespace v8_inspector { |  | 
| 13 |  | 
| 14 namespace { |  | 
| 15 |  | 
| 16 String16 findMagicComment(const String16& content, const String16& name, bool mu
     ltiline) |  | 
| 17 { |  | 
| 18     DCHECK(name.find("=") == String16::kNotFound); |  | 
| 19     unsigned length = content.length(); |  | 
| 20     unsigned nameLength = name.length(); |  | 
| 21 |  | 
| 22     size_t pos = length; |  | 
| 23     size_t equalSignPos = 0; |  | 
| 24     size_t closingCommentPos = 0; |  | 
| 25     while (true) { |  | 
| 26         pos = content.reverseFind(name, pos); |  | 
| 27         if (pos == String16::kNotFound) |  | 
| 28             return String16(); |  | 
| 29 |  | 
| 30         // Check for a /\/[\/*][@#][ \t]/ regexp (length of 4) before found name
     . |  | 
| 31         if (pos < 4) |  | 
| 32             return String16(); |  | 
| 33         pos -= 4; |  | 
| 34         if (content[pos] != '/') |  | 
| 35             continue; |  | 
| 36         if ((content[pos + 1] != '/' || multiline) |  | 
| 37             && (content[pos + 1] != '*' || !multiline)) |  | 
| 38             continue; |  | 
| 39         if (content[pos + 2] != '#' && content[pos + 2] != '@') |  | 
| 40             continue; |  | 
| 41         if (content[pos + 3] != ' ' && content[pos + 3] != '\t') |  | 
| 42             continue; |  | 
| 43         equalSignPos = pos + 4 + nameLength; |  | 
| 44         if (equalSignPos < length && content[equalSignPos] != '=') |  | 
| 45             continue; |  | 
| 46         if (multiline) { |  | 
| 47             closingCommentPos = content.find("*/", equalSignPos + 1); |  | 
| 48             if (closingCommentPos == String16::kNotFound) |  | 
| 49                 return String16(); |  | 
| 50         } |  | 
| 51 |  | 
| 52         break; |  | 
| 53     } |  | 
| 54 |  | 
| 55     DCHECK(equalSignPos); |  | 
| 56     DCHECK(!multiline || closingCommentPos); |  | 
| 57     size_t urlPos = equalSignPos + 1; |  | 
| 58     String16 match = multiline |  | 
| 59         ? content.substring(urlPos, closingCommentPos - urlPos) |  | 
| 60         : content.substring(urlPos); |  | 
| 61 |  | 
| 62     size_t newLine = match.find("\n"); |  | 
| 63     if (newLine != String16::kNotFound) |  | 
| 64         match = match.substring(0, newLine); |  | 
| 65     match = match.stripWhiteSpace(); |  | 
| 66 |  | 
| 67     for (unsigned i = 0; i < match.length(); ++i) { |  | 
| 68         UChar c = match[i]; |  | 
| 69         if (c == '"' || c == '\'' || c == ' ' || c == '\t') |  | 
| 70             return ""; |  | 
| 71     } |  | 
| 72 |  | 
| 73     return match; |  | 
| 74 } |  | 
| 75 |  | 
| 76 String16 createSearchRegexSource(const String16& text) |  | 
| 77 { |  | 
| 78     String16Builder result; |  | 
| 79 |  | 
| 80     for (unsigned i = 0; i < text.length(); i++) { |  | 
| 81         UChar c = text[i]; |  | 
| 82         if (c == '[' || c == ']' || c == '(' || c == ')' || c == '{' || c == '}' |  | 
| 83             || c == '+' || c == '-' || c == '*' || c == '.' || c == ',' || c == 
     '?' |  | 
| 84             || c == '\\' || c == '^' || c == '$' || c == '|') { |  | 
| 85             result.append('\\'); |  | 
| 86         } |  | 
| 87         result.append(c); |  | 
| 88     } |  | 
| 89 |  | 
| 90     return result.toString(); |  | 
| 91 } |  | 
| 92 |  | 
| 93 std::unique_ptr<std::vector<unsigned>> lineEndings(const String16& text) |  | 
| 94 { |  | 
| 95     std::unique_ptr<std::vector<unsigned>> result(new std::vector<unsigned>()); |  | 
| 96 |  | 
| 97     const String16 lineEndString = "\n"; |  | 
| 98     unsigned start = 0; |  | 
| 99     while (start < text.length()) { |  | 
| 100         size_t lineEnd = text.find(lineEndString, start); |  | 
| 101         if (lineEnd == String16::kNotFound) |  | 
| 102             break; |  | 
| 103 |  | 
| 104         result->push_back(static_cast<unsigned>(lineEnd)); |  | 
| 105         start = lineEnd + 1; |  | 
| 106     } |  | 
| 107     result->push_back(static_cast<unsigned>(text.length())); |  | 
| 108 |  | 
| 109     return result; |  | 
| 110 } |  | 
| 111 |  | 
| 112 std::vector<std::pair<int, String16>> scriptRegexpMatchesByLines(const V8Regex& 
     regex, const String16& text) |  | 
| 113 { |  | 
| 114     std::vector<std::pair<int, String16>> result; |  | 
| 115     if (text.isEmpty()) |  | 
| 116         return result; |  | 
| 117 |  | 
| 118     std::unique_ptr<std::vector<unsigned>> endings(lineEndings(text)); |  | 
| 119     unsigned size = endings->size(); |  | 
| 120     unsigned start = 0; |  | 
| 121     for (unsigned lineNumber = 0; lineNumber < size; ++lineNumber) { |  | 
| 122         unsigned lineEnd = endings->at(lineNumber); |  | 
| 123         String16 line = text.substring(start, lineEnd - start); |  | 
| 124         if (line.length() && line[line.length() - 1] == '\r') |  | 
| 125             line = line.substring(0, line.length() - 1); |  | 
| 126 |  | 
| 127         int matchLength; |  | 
| 128         if (regex.match(line, 0, &matchLength) != -1) |  | 
| 129             result.push_back(std::pair<int, String16>(lineNumber, line)); |  | 
| 130 |  | 
| 131         start = lineEnd + 1; |  | 
| 132     } |  | 
| 133     return result; |  | 
| 134 } |  | 
| 135 |  | 
| 136 std::unique_ptr<protocol::Debugger::SearchMatch> buildObjectForSearchMatch(int l
     ineNumber, const String16& lineContent) |  | 
| 137 { |  | 
| 138     return protocol::Debugger::SearchMatch::create() |  | 
| 139         .setLineNumber(lineNumber) |  | 
| 140         .setLineContent(lineContent) |  | 
| 141         .build(); |  | 
| 142 } |  | 
| 143 |  | 
| 144 std::unique_ptr<V8Regex> createSearchRegex(V8InspectorImpl* inspector, const Str
     ing16& query, bool caseSensitive, bool isRegex) |  | 
| 145 { |  | 
| 146     String16 regexSource = isRegex ? query : createSearchRegexSource(query); |  | 
| 147     return wrapUnique(new V8Regex(inspector, regexSource, caseSensitive)); |  | 
| 148 } |  | 
| 149 |  | 
| 150 } // namespace |  | 
| 151 |  | 
| 152 std::vector<std::unique_ptr<protocol::Debugger::SearchMatch>> searchInTextByLine
     sImpl(V8InspectorSession* session, const String16& text, const String16& query, 
     const bool caseSensitive, const bool isRegex) |  | 
| 153 { |  | 
| 154     std::unique_ptr<V8Regex> regex = createSearchRegex(static_cast<V8InspectorSe
     ssionImpl*>(session)->inspector(), query, caseSensitive, isRegex); |  | 
| 155     std::vector<std::pair<int, String16>> matches = scriptRegexpMatchesByLines(*
     regex.get(), text); |  | 
| 156 |  | 
| 157     std::vector<std::unique_ptr<protocol::Debugger::SearchMatch>> result; |  | 
| 158     for (const auto& match : matches) |  | 
| 159         result.push_back(buildObjectForSearchMatch(match.first, match.second)); |  | 
| 160     return result; |  | 
| 161 } |  | 
| 162 |  | 
| 163 String16 findSourceURL(const String16& content, bool multiline) |  | 
| 164 { |  | 
| 165     return findMagicComment(content, "sourceURL", multiline); |  | 
| 166 } |  | 
| 167 |  | 
| 168 String16 findSourceMapURL(const String16& content, bool multiline) |  | 
| 169 { |  | 
| 170     return findMagicComment(content, "sourceMappingURL", multiline); |  | 
| 171 } |  | 
| 172 |  | 
| 173 } // namespace v8_inspector |  | 
| OLD | NEW | 
|---|