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/inspected-context.h" | 7 #include "src/inspector/inspected-context.h" |
8 #include "src/inspector/string-util.h" | 8 #include "src/inspector/string-util.h" |
| 9 #include "src/inspector/wasm-translation.h" |
9 | 10 |
10 namespace v8_inspector { | 11 namespace v8_inspector { |
11 | 12 |
12 namespace { | 13 namespace { |
13 | 14 |
14 const char hexDigits[17] = "0123456789ABCDEF"; | 15 const char hexDigits[17] = "0123456789ABCDEF"; |
15 | 16 |
16 void appendUnsignedAsHex(uint64_t number, String16Builder* destination) { | 17 void appendUnsignedAsHex(uint64_t number, String16Builder* destination) { |
17 for (size_t i = 0; i < 8; ++i) { | 18 for (size_t i = 0; i < 8; ++i) { |
18 UChar c = hexDigits[number & 0xF]; | 19 UChar c = hexDigits[number & 0xF]; |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
62 } | 63 } |
63 | 64 |
64 for (size_t i = 0; i < hashesSize; ++i) | 65 for (size_t i = 0; i < hashesSize; ++i) |
65 hashes[i] = (hashes[i] + zi[i] * (prime[i] - 1)) % prime[i]; | 66 hashes[i] = (hashes[i] + zi[i] * (prime[i] - 1)) % prime[i]; |
66 | 67 |
67 String16Builder hash; | 68 String16Builder hash; |
68 for (size_t i = 0; i < hashesSize; ++i) appendUnsignedAsHex(hashes[i], &hash); | 69 for (size_t i = 0; i < hashesSize; ++i) appendUnsignedAsHex(hashes[i], &hash); |
69 return hash.toString(); | 70 return hash.toString(); |
70 } | 71 } |
71 | 72 |
| 73 void TranslateProtocolLocationToV8Location(WasmTranslation* wasmTranslation, |
| 74 v8::debug::Location* loc, |
| 75 const String16& scriptId, |
| 76 const String16& expectedV8ScriptId) { |
| 77 if (loc->IsEmpty()) return; |
| 78 int lineNumber = loc->GetLineNumber(); |
| 79 int columnNumber = loc->GetColumnNumber(); |
| 80 String16 translatedScriptId = scriptId; |
| 81 wasmTranslation->TranslateProtocolLocationToWasmScriptLocation( |
| 82 &translatedScriptId, &lineNumber, &columnNumber); |
| 83 DCHECK_EQ(expectedV8ScriptId.utf8(), translatedScriptId.utf8()); |
| 84 *loc = v8::debug::Location(lineNumber, columnNumber); |
| 85 } |
| 86 |
| 87 void TranslateV8LocationToProtocolLocation( |
| 88 WasmTranslation* wasmTranslation, v8::debug::Location* loc, |
| 89 const String16& scriptId, const String16& expectedProtocolScriptId) { |
| 90 int lineNumber = loc->GetLineNumber(); |
| 91 int columnNumber = loc->GetColumnNumber(); |
| 92 String16 translatedScriptId = scriptId; |
| 93 wasmTranslation->TranslateWasmScriptLocationToProtocolLocation( |
| 94 &translatedScriptId, &lineNumber, &columnNumber); |
| 95 DCHECK_EQ(expectedProtocolScriptId.utf8(), translatedScriptId.utf8()); |
| 96 *loc = v8::debug::Location(lineNumber, columnNumber); |
| 97 } |
| 98 |
72 class ActualScript : public V8DebuggerScript { | 99 class ActualScript : public V8DebuggerScript { |
73 friend class V8DebuggerScript; | 100 friend class V8DebuggerScript; |
74 | 101 |
75 public: | 102 public: |
76 ActualScript(v8::Isolate* isolate, v8::Local<v8::debug::Script> script, | 103 ActualScript(v8::Isolate* isolate, v8::Local<v8::debug::Script> script, |
77 bool isLiveEdit) | 104 bool isLiveEdit) |
78 : V8DebuggerScript(isolate, String16::fromInteger(script->Id()), | 105 : V8DebuggerScript(isolate, String16::fromInteger(script->Id()), |
79 GetNameOrSourceUrl(script)), | 106 GetNameOrSourceUrl(script)), |
80 m_isLiveEdit(isLiveEdit) { | 107 m_isLiveEdit(isLiveEdit) { |
81 v8::Local<v8::String> tmp; | 108 v8::Local<v8::String> tmp; |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
164 String16 m_sourceMappingURL; | 191 String16 m_sourceMappingURL; |
165 v8::Global<v8::String> m_sourceObj; | 192 v8::Global<v8::String> m_sourceObj; |
166 bool m_isLiveEdit = false; | 193 bool m_isLiveEdit = false; |
167 v8::Global<v8::debug::Script> m_script; | 194 v8::Global<v8::debug::Script> m_script; |
168 }; | 195 }; |
169 | 196 |
170 class WasmVirtualScript : public V8DebuggerScript { | 197 class WasmVirtualScript : public V8DebuggerScript { |
171 friend class V8DebuggerScript; | 198 friend class V8DebuggerScript; |
172 | 199 |
173 public: | 200 public: |
174 WasmVirtualScript(v8::Isolate* isolate, | 201 WasmVirtualScript(v8::Isolate* isolate, WasmTranslation* wasmTranslation, |
175 v8::Local<v8::debug::WasmScript> script, String16 id, | 202 v8::Local<v8::debug::WasmScript> script, String16 id, |
176 String16 url, String16 source) | 203 String16 url, String16 source) |
177 : V8DebuggerScript(isolate, std::move(id), std::move(url)), | 204 : V8DebuggerScript(isolate, std::move(id), std::move(url)), |
178 m_script(isolate, script) { | 205 m_script(isolate, script), |
| 206 m_wasmTranslation(wasmTranslation) { |
179 int num_lines = 0; | 207 int num_lines = 0; |
180 int last_newline = -1; | 208 int last_newline = -1; |
181 size_t next_newline = source.find('\n', last_newline + 1); | 209 size_t next_newline = source.find('\n', last_newline + 1); |
182 while (next_newline != String16::kNotFound) { | 210 while (next_newline != String16::kNotFound) { |
183 last_newline = static_cast<int>(next_newline); | 211 last_newline = static_cast<int>(next_newline); |
184 next_newline = source.find('\n', last_newline + 1); | 212 next_newline = source.find('\n', last_newline + 1); |
185 ++num_lines; | 213 ++num_lines; |
186 } | 214 } |
187 m_endLine = num_lines; | 215 m_endLine = num_lines; |
188 m_endColumn = static_cast<int>(source.length()) - last_newline - 1; | 216 m_endColumn = static_cast<int>(source.length()) - last_newline - 1; |
189 m_source = std::move(source); | 217 m_source = std::move(source); |
190 } | 218 } |
191 | 219 |
192 const String16& sourceMappingURL() const override { return emptyString(); } | 220 const String16& sourceMappingURL() const override { return emptyString(); } |
193 bool isLiveEdit() const override { return false; } | 221 bool isLiveEdit() const override { return false; } |
194 void setSourceMappingURL(const String16&) override {} | 222 void setSourceMappingURL(const String16&) override {} |
195 | 223 |
196 bool getPossibleBreakpoints( | 224 bool getPossibleBreakpoints( |
197 const v8::debug::Location& start, const v8::debug::Location& end, | 225 const v8::debug::Location& start, const v8::debug::Location& end, |
198 std::vector<v8::debug::Location>* locations) override { | 226 std::vector<v8::debug::Location>* locations) override { |
199 // TODO(clemensh): Returning false produces the protocol error "Internal | 227 v8::HandleScope scope(m_isolate); |
200 // error". Implement and fix expected output of | 228 v8::Local<v8::debug::Script> script = m_script.Get(m_isolate); |
201 // wasm-get-breakable-locations.js. | 229 String16 v8ScriptId = String16::fromInteger(script->Id()); |
202 return false; | 230 |
| 231 v8::debug::Location translatedStart = start; |
| 232 TranslateProtocolLocationToV8Location(m_wasmTranslation, &translatedStart, |
| 233 scriptId(), v8ScriptId); |
| 234 |
| 235 v8::debug::Location translatedEnd = end; |
| 236 if (translatedEnd.IsEmpty()) { |
| 237 // Stop before the start of the next function. |
| 238 translatedEnd = |
| 239 v8::debug::Location(translatedStart.GetLineNumber() + 1, 0); |
| 240 } else { |
| 241 TranslateProtocolLocationToV8Location(m_wasmTranslation, &translatedEnd, |
| 242 scriptId(), v8ScriptId); |
| 243 } |
| 244 |
| 245 bool success = script->GetPossibleBreakpoints(translatedStart, |
| 246 translatedEnd, locations); |
| 247 for (v8::debug::Location& loc : *locations) { |
| 248 TranslateV8LocationToProtocolLocation(m_wasmTranslation, &loc, v8ScriptId, |
| 249 scriptId()); |
| 250 } |
| 251 return success; |
203 } | 252 } |
204 | 253 |
205 void resetBlackboxedStateCache() override {} | 254 void resetBlackboxedStateCache() override {} |
206 | 255 |
207 private: | 256 private: |
208 static const String16& emptyString() { | 257 static const String16& emptyString() { |
209 static const String16 singleEmptyString; | 258 static const String16 singleEmptyString; |
210 return singleEmptyString; | 259 return singleEmptyString; |
211 } | 260 } |
212 | 261 |
213 v8::Global<v8::debug::WasmScript> m_script; | 262 v8::Global<v8::debug::WasmScript> m_script; |
| 263 WasmTranslation* m_wasmTranslation; |
214 }; | 264 }; |
215 | 265 |
216 } // namespace | 266 } // namespace |
217 | 267 |
218 std::unique_ptr<V8DebuggerScript> V8DebuggerScript::Create( | 268 std::unique_ptr<V8DebuggerScript> V8DebuggerScript::Create( |
219 v8::Isolate* isolate, v8::Local<v8::debug::Script> scriptObj, | 269 v8::Isolate* isolate, v8::Local<v8::debug::Script> scriptObj, |
220 bool isLiveEdit) { | 270 bool isLiveEdit) { |
221 return std::unique_ptr<ActualScript>( | 271 return std::unique_ptr<ActualScript>( |
222 new ActualScript(isolate, scriptObj, isLiveEdit)); | 272 new ActualScript(isolate, scriptObj, isLiveEdit)); |
223 } | 273 } |
224 | 274 |
225 std::unique_ptr<V8DebuggerScript> V8DebuggerScript::CreateWasm( | 275 std::unique_ptr<V8DebuggerScript> V8DebuggerScript::CreateWasm( |
226 v8::Isolate* isolate, v8::Local<v8::debug::WasmScript> underlyingScript, | 276 v8::Isolate* isolate, WasmTranslation* wasmTranslation, |
227 String16 id, String16 url, String16 source) { | 277 v8::Local<v8::debug::WasmScript> underlyingScript, String16 id, |
| 278 String16 url, String16 source) { |
228 return std::unique_ptr<WasmVirtualScript>( | 279 return std::unique_ptr<WasmVirtualScript>( |
229 new WasmVirtualScript(isolate, underlyingScript, std::move(id), | 280 new WasmVirtualScript(isolate, wasmTranslation, underlyingScript, |
230 std::move(url), std::move(source))); | 281 std::move(id), std::move(url), std::move(source))); |
231 } | 282 } |
232 | 283 |
233 V8DebuggerScript::V8DebuggerScript(v8::Isolate* isolate, String16 id, | 284 V8DebuggerScript::V8DebuggerScript(v8::Isolate* isolate, String16 id, |
234 String16 url) | 285 String16 url) |
235 : m_id(std::move(id)), m_url(std::move(url)), m_isolate(isolate) {} | 286 : m_id(std::move(id)), m_url(std::move(url)), m_isolate(isolate) {} |
236 | 287 |
237 V8DebuggerScript::~V8DebuggerScript() {} | 288 V8DebuggerScript::~V8DebuggerScript() {} |
238 | 289 |
239 const String16& V8DebuggerScript::sourceURL() const { | 290 const String16& V8DebuggerScript::sourceURL() const { |
240 return m_sourceURL.isEmpty() ? m_url : m_sourceURL; | 291 return m_sourceURL.isEmpty() ? m_url : m_sourceURL; |
241 } | 292 } |
242 | 293 |
243 const String16& V8DebuggerScript::hash(v8::Isolate* isolate) const { | 294 const String16& V8DebuggerScript::hash(v8::Isolate* isolate) const { |
244 if (m_hash.isEmpty()) m_hash = calculateHash(source(isolate)); | 295 if (m_hash.isEmpty()) m_hash = calculateHash(source(isolate)); |
245 DCHECK(!m_hash.isEmpty()); | 296 DCHECK(!m_hash.isEmpty()); |
246 return m_hash; | 297 return m_hash; |
247 } | 298 } |
248 | 299 |
249 void V8DebuggerScript::setSourceURL(const String16& sourceURL) { | 300 void V8DebuggerScript::setSourceURL(const String16& sourceURL) { |
250 m_sourceURL = sourceURL; | 301 m_sourceURL = sourceURL; |
251 } | 302 } |
252 | 303 |
253 } // namespace v8_inspector | 304 } // namespace v8_inspector |
OLD | NEW |