OLD | NEW |
---|---|
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/inspector/v8-debugger-script.h" | 5 #include "src/inspector/v8-debugger-script.h" |
6 | 6 |
7 #include "src/inspector/string-util.h" | 7 #include "src/inspector/string-util.h" |
8 | 8 |
9 namespace v8_inspector { | 9 namespace v8_inspector { |
10 | 10 |
11 static const char hexDigits[17] = "0123456789ABCDEF"; | 11 namespace { |
12 | 12 |
13 static void appendUnsignedAsHex(uint64_t number, String16Builder* destination) { | 13 const char hexDigits[17] = "0123456789ABCDEF"; |
14 | |
15 void appendUnsignedAsHex(uint64_t number, String16Builder* destination) { | |
14 for (size_t i = 0; i < 8; ++i) { | 16 for (size_t i = 0; i < 8; ++i) { |
15 UChar c = hexDigits[number & 0xF]; | 17 UChar c = hexDigits[number & 0xF]; |
16 destination->append(c); | 18 destination->append(c); |
17 number >>= 4; | 19 number >>= 4; |
18 } | 20 } |
19 } | 21 } |
20 | 22 |
21 // Hash algorithm for substrings is described in "Über die Komplexität der | 23 // Hash algorithm for substrings is described in "Über die Komplexität der |
22 // Multiplikation in | 24 // Multiplikation in |
23 // eingeschränkten Branchingprogrammmodellen" by Woelfe. | 25 // eingeschränkten Branchingprogrammmodellen" by Woelfe. |
24 // http://opendatastructures.org/versions/edition-0.1d/ods-java/node33.html#SECT ION00832000000000000000 | 26 // http://opendatastructures.org/versions/edition-0.1d/ods-java/node33.html#SECT ION00832000000000000000 |
25 static String16 calculateHash(const String16& str) { | 27 String16 calculateHash(const String16& str) { |
26 static uint64_t prime[] = {0x3FB75161, 0xAB1F4E4F, 0x82675BC5, 0xCD924D35, | 28 static uint64_t prime[] = {0x3FB75161, 0xAB1F4E4F, 0x82675BC5, 0xCD924D35, |
27 0x81ABE279}; | 29 0x81ABE279}; |
28 static uint64_t random[] = {0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, | 30 static uint64_t random[] = {0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, |
29 0xC3D2E1F0}; | 31 0xC3D2E1F0}; |
30 static uint32_t randomOdd[] = {0xB4663807, 0xCC322BF5, 0xD4F91BBD, 0xA7BEA11D, | 32 static uint32_t randomOdd[] = {0xB4663807, 0xCC322BF5, 0xD4F91BBD, 0xA7BEA11D, |
31 0x8F462907}; | 33 0x8F462907}; |
32 | 34 |
33 uint64_t hashes[] = {0, 0, 0, 0, 0}; | 35 uint64_t hashes[] = {0, 0, 0, 0, 0}; |
34 uint64_t zi[] = {1, 1, 1, 1, 1}; | 36 uint64_t zi[] = {1, 1, 1, 1, 1}; |
35 | 37 |
(...skipping 23 matching lines...) Expand all Loading... | |
59 } | 61 } |
60 | 62 |
61 for (size_t i = 0; i < hashesSize; ++i) | 63 for (size_t i = 0; i < hashesSize; ++i) |
62 hashes[i] = (hashes[i] + zi[i] * (prime[i] - 1)) % prime[i]; | 64 hashes[i] = (hashes[i] + zi[i] * (prime[i] - 1)) % prime[i]; |
63 | 65 |
64 String16Builder hash; | 66 String16Builder hash; |
65 for (size_t i = 0; i < hashesSize; ++i) appendUnsignedAsHex(hashes[i], &hash); | 67 for (size_t i = 0; i < hashesSize; ++i) appendUnsignedAsHex(hashes[i], &hash); |
66 return hash.toString(); | 68 return hash.toString(); |
67 } | 69 } |
68 | 70 |
69 V8DebuggerScript::V8DebuggerScript(v8::Isolate* isolate, | 71 class ActualScript : public V8DebuggerScript { |
70 v8::Local<v8::DebugInterface::Script> script, | 72 friend class V8DebuggerScript; |
71 bool isLiveEdit) { | 73 |
72 m_isolate = script->GetIsolate(); | 74 public: |
73 m_id = String16::fromInteger(script->Id()); | 75 ActualScript(v8::Local<v8::DebugInterface::Script> script, String16 url) |
76 : V8DebuggerScript(script->GetIsolate(), | |
77 String16::fromInteger(script->Id()), std::move(url)) {} | |
78 | |
79 bool isLiveEdit() const override { return m_isLiveEdit; } | |
80 | |
81 const String16& executionContextAuxData() const override { | |
82 return m_executionContextAuxData; | |
83 } | |
84 | |
85 const String16& sourceMappingURL() const override { | |
86 return m_sourceMappingURL; | |
87 } | |
88 | |
89 String16 source(v8::Isolate* isolate) const override { | |
90 if (!m_sourceObj.IsEmpty()) | |
91 return toProtocolString(m_sourceObj.Get(isolate)); | |
92 return V8DebuggerScript::source(isolate); | |
93 } | |
94 | |
95 void setSourceMappingURL(const String16& sourceMappingURL) override { | |
96 m_sourceMappingURL = sourceMappingURL; | |
97 } | |
98 | |
99 void setSource(v8::Local<v8::String> source) override { | |
100 m_source = String16(); | |
101 m_sourceObj.Reset(m_isolate, source); | |
102 m_hash = String16(); | |
103 } | |
104 | |
105 bool getPossibleBreakpoints( | |
106 const v8::DebugInterface::Location& start, | |
107 const v8::DebugInterface::Location& end, | |
108 std::vector<v8::DebugInterface::Location>* locations) override { | |
109 v8::HandleScope scope(m_isolate); | |
110 v8::Local<v8::DebugInterface::Script> script = m_script.Get(m_isolate); | |
111 return script->GetPossibleBreakpoints(start, end, locations); | |
112 } | |
113 | |
114 private: | |
115 String16 m_sourceMappingURL; | |
116 v8::Global<v8::String> m_sourceObj; | |
117 String16 m_executionContextAuxData; | |
118 bool m_isLiveEdit = false; | |
119 v8::Global<v8::DebugInterface::Script> m_script; | |
120 }; | |
121 | |
122 class WasmVirtualScript : public V8DebuggerScript { | |
123 friend class V8DebuggerScript; | |
124 | |
125 public: | |
126 WasmVirtualScript(v8::Local<v8::DebugInterface::Script> script, String16 id, | |
127 String16 url, String16 source) | |
128 : V8DebuggerScript(script->GetIsolate(), std::move(id), std::move(url)), | |
129 m_script(script->GetIsolate(), script) { | |
130 m_source = std::move(source); | |
131 } | |
132 | |
133 const String16& sourceMappingURL() const override { return emptyString(); } | |
134 const String16& executionContextAuxData() const override { | |
135 return emptyString(); | |
136 } | |
137 bool isLiveEdit() const override { return false; } | |
138 | |
139 bool getPossibleBreakpoints( | |
140 const v8::DebugInterface::Location& start, | |
141 const v8::DebugInterface::Location& end, | |
142 std::vector<v8::DebugInterface::Location>* locations) override { | |
143 // TODO(clemensh): Returning false produces the protocol error "Internal | |
144 // error". Implement and fix expected output of | |
145 // wasm-get-breakable-locations.js. | |
146 return false; | |
147 } | |
148 | |
149 private: | |
150 static const String16& emptyString() { | |
151 static const String16 singleEmptyString; | |
152 return singleEmptyString; | |
153 } | |
154 | |
155 v8::Global<v8::DebugInterface::Script> m_script; | |
156 }; | |
157 | |
158 } // namespace | |
159 | |
160 std::unique_ptr<V8DebuggerScript> V8DebuggerScript::Create( | |
161 v8::Isolate* isolate, v8::Local<v8::DebugInterface::Script> scriptObj, | |
162 bool isLiveEdit) { | |
163 String16 url; | |
164 String16 sourceUrl; | |
74 v8::Local<v8::String> tmp; | 165 v8::Local<v8::String> tmp; |
75 if (script->Name().ToLocal(&tmp)) m_url = toProtocolString(tmp); | 166 if (scriptObj->Name().ToLocal(&tmp)) url = toProtocolString(tmp); |
76 if (script->SourceURL().ToLocal(&tmp)) { | 167 if (scriptObj->SourceURL().ToLocal(&tmp)) { |
77 m_sourceURL = toProtocolString(tmp); | 168 sourceUrl = toProtocolString(tmp); |
78 if (m_url.isEmpty()) m_url = toProtocolString(tmp); | 169 if (url.isEmpty()) url = sourceUrl; |
79 } | 170 } |
80 if (script->SourceMappingURL().ToLocal(&tmp)) | 171 std::unique_ptr<ActualScript> script(new ActualScript(scriptObj, url)); |
81 m_sourceMappingURL = toProtocolString(tmp); | 172 script->m_sourceURL = std::move(sourceUrl); |
kozy
2016/11/30 18:34:37
Could we move all this logic to ActualScript cstor
Clemens Hammacher
2016/12/02 17:44:13
Done, also for WasmVirtualScript.
| |
82 m_startLine = script->LineOffset(); | 173 if (scriptObj->SourceMappingURL().ToLocal(&tmp)) |
83 m_startColumn = script->ColumnOffset(); | 174 script->m_sourceMappingURL = toProtocolString(tmp); |
84 std::vector<int> lineEnds = script->LineEnds(); | 175 script->m_startLine = scriptObj->LineOffset(); |
176 script->m_startColumn = scriptObj->ColumnOffset(); | |
177 std::vector<int> lineEnds = scriptObj->LineEnds(); | |
85 CHECK(lineEnds.size()); | 178 CHECK(lineEnds.size()); |
86 int source_length = lineEnds[lineEnds.size() - 1]; | 179 int source_length = lineEnds[lineEnds.size() - 1]; |
87 if (lineEnds.size()) { | 180 if (lineEnds.size()) { |
88 m_endLine = static_cast<int>(lineEnds.size()) + m_startLine - 1; | 181 script->m_endLine = |
182 static_cast<int>(lineEnds.size()) + script->m_startLine - 1; | |
89 if (lineEnds.size() > 1) { | 183 if (lineEnds.size() > 1) { |
90 m_endColumn = source_length - lineEnds[lineEnds.size() - 2] - 1; | 184 script->m_endColumn = source_length - lineEnds[lineEnds.size() - 2] - 1; |
91 } else { | 185 } else { |
92 m_endColumn = source_length + m_startColumn; | 186 script->m_endColumn = source_length + script->m_startColumn; |
93 } | 187 } |
94 } else { | 188 } else { |
95 m_endLine = m_startLine; | 189 script->m_endLine = script->m_startLine; |
96 m_endColumn = m_startColumn; | 190 script->m_endColumn = script->m_startColumn; |
97 } | 191 } |
98 | 192 |
99 if (script->ContextData().ToLocal(&tmp)) { | 193 if (scriptObj->ContextData().ToLocal(&tmp)) { |
100 String16 contextData = toProtocolString(tmp); | 194 String16 contextData = toProtocolString(tmp); |
101 size_t firstComma = contextData.find(",", 0); | 195 size_t firstComma = contextData.find(",", 0); |
102 size_t secondComma = firstComma != String16::kNotFound | 196 size_t secondComma = firstComma != String16::kNotFound |
103 ? contextData.find(",", firstComma + 1) | 197 ? contextData.find(",", firstComma + 1) |
104 : String16::kNotFound; | 198 : String16::kNotFound; |
105 if (secondComma != String16::kNotFound) { | 199 if (secondComma != String16::kNotFound) { |
106 String16 executionContextId = | 200 String16 executionContextId = |
107 contextData.substring(firstComma + 1, secondComma - firstComma - 1); | 201 contextData.substring(firstComma + 1, secondComma - firstComma - 1); |
108 bool isOk = false; | 202 bool isOk = false; |
109 m_executionContextId = executionContextId.toInteger(&isOk); | 203 script->m_executionContextId = executionContextId.toInteger(&isOk); |
110 if (!isOk) m_executionContextId = 0; | 204 if (!isOk) script->m_executionContextId = 0; |
111 m_executionContextAuxData = contextData.substring(secondComma + 1); | 205 script->m_executionContextAuxData = |
206 contextData.substring(secondComma + 1); | |
112 } | 207 } |
113 } | 208 } |
114 | 209 |
115 m_isLiveEdit = isLiveEdit; | 210 script->m_isLiveEdit = isLiveEdit; |
116 | 211 |
117 if (script->Source().ToLocal(&tmp)) { | 212 if (scriptObj->Source().ToLocal(&tmp)) { |
118 m_sourceObj.Reset(m_isolate, tmp); | 213 script->m_sourceObj.Reset(script->m_isolate, tmp); |
119 String16 source = toProtocolString(tmp); | 214 String16 source = toProtocolString(tmp); |
120 // V8 will not count last line if script source ends with \n. | 215 // V8 will not count last line if script source ends with \n. |
121 if (source.length() > 1 && source[source.length() - 1] == '\n') { | 216 if (source.length() > 1 && source[source.length() - 1] == '\n') { |
122 m_endLine++; | 217 script->m_endLine++; |
123 m_endColumn = 0; | 218 script->m_endColumn = 0; |
124 } | 219 } |
125 } | 220 } |
126 | 221 |
127 m_script.Reset(m_isolate, script); | 222 script->m_script.Reset(script->m_isolate, scriptObj); |
223 return std::move(script); | |
128 } | 224 } |
129 | 225 |
130 V8DebuggerScript::V8DebuggerScript(String16 id, String16 url, String16 source) | 226 std::unique_ptr<V8DebuggerScript> V8DebuggerScript::CreateWasm( |
131 : m_id(std::move(id)), m_url(std::move(url)), m_source(std::move(source)) { | 227 v8::Local<v8::DebugInterface::Script> script, String16 id, String16 url, |
228 String16 source) { | |
132 int num_lines = 0; | 229 int num_lines = 0; |
133 int last_newline = -1; | 230 int last_newline = -1; |
134 size_t next_newline = m_source.find('\n', last_newline + 1); | 231 size_t next_newline = source.find('\n', last_newline + 1); |
135 while (next_newline != String16::kNotFound) { | 232 while (next_newline != String16::kNotFound) { |
136 last_newline = static_cast<int>(next_newline); | 233 last_newline = static_cast<int>(next_newline); |
137 next_newline = m_source.find('\n', last_newline + 1); | 234 next_newline = source.find('\n', last_newline + 1); |
138 ++num_lines; | 235 ++num_lines; |
139 } | 236 } |
140 m_endLine = num_lines; | 237 int m_endLine = num_lines; |
141 m_endColumn = static_cast<int>(m_source.length()) - last_newline - 1; | 238 int m_endColumn = static_cast<int>(source.length()) - last_newline - 1; |
239 return std::unique_ptr<WasmVirtualScript>(new WasmVirtualScript( | |
240 script, std::move(id), std::move(url), std::move(source))); | |
142 } | 241 } |
143 | 242 |
144 V8DebuggerScript::~V8DebuggerScript() {} | 243 V8DebuggerScript::~V8DebuggerScript() {} |
145 | 244 |
146 const String16& V8DebuggerScript::sourceURL() const { | 245 const String16& V8DebuggerScript::sourceURL() const { |
147 return m_sourceURL.isEmpty() ? m_url : m_sourceURL; | 246 return m_sourceURL.isEmpty() ? m_url : m_sourceURL; |
148 } | 247 } |
149 | 248 |
150 String16 V8DebuggerScript::source(v8::Isolate* isolate) const { | |
151 if (m_sourceObj.IsEmpty()) return m_source; | |
152 return toProtocolString(m_sourceObj.Get(isolate)); | |
153 } | |
154 | |
155 const String16& V8DebuggerScript::hash(v8::Isolate* isolate) const { | 249 const String16& V8DebuggerScript::hash(v8::Isolate* isolate) const { |
156 if (m_hash.isEmpty()) m_hash = calculateHash(source(isolate)); | 250 if (m_hash.isEmpty()) m_hash = calculateHash(source(isolate)); |
157 DCHECK(!m_hash.isEmpty()); | 251 DCHECK(!m_hash.isEmpty()); |
158 return m_hash; | 252 return m_hash; |
159 } | 253 } |
160 | 254 |
161 void V8DebuggerScript::setSourceURL(const String16& sourceURL) { | 255 void V8DebuggerScript::setSourceURL(const String16& sourceURL) { |
162 m_sourceURL = sourceURL; | 256 m_sourceURL = sourceURL; |
163 } | 257 } |
164 | 258 |
165 void V8DebuggerScript::setSourceMappingURL(const String16& sourceMappingURL) { | 259 V8DebuggerScript::V8DebuggerScript(v8::Isolate* isolate, String16 id, |
166 m_sourceMappingURL = sourceMappingURL; | 260 String16 url) |
167 } | 261 : m_id(std::move(id)), m_url(std::move(url)), m_isolate(isolate) {} |
168 | |
169 void V8DebuggerScript::setSource(v8::Local<v8::String> source) { | |
170 m_source = String16(); | |
171 m_sourceObj.Reset(m_isolate, source); | |
172 m_hash = String16(); | |
173 } | |
174 | |
175 bool V8DebuggerScript::getPossibleBreakpoints( | |
176 const v8::DebugInterface::Location& start, | |
177 const v8::DebugInterface::Location& end, | |
178 std::vector<v8::DebugInterface::Location>* locations) { | |
179 v8::HandleScope scope(m_isolate); | |
180 v8::Local<v8::DebugInterface::Script> script = m_script.Get(m_isolate); | |
181 return script->GetPossibleBreakpoints(start, end, locations); | |
182 } | |
183 | 262 |
184 } // namespace v8_inspector | 263 } // namespace v8_inspector |
OLD | NEW |