Index: src/api.cc |
diff --git a/src/api.cc b/src/api.cc |
index 838f52f8032d092f49b1d06afd18638b9e9f9800..20eb44d834cf480d54bdd48bfea7c9e3653f5c34 100644 |
--- a/src/api.cc |
+++ b/src/api.cc |
@@ -8950,6 +8950,82 @@ MaybeLocal<String> DebugInterface::Script::Source() const { |
handle_scope.CloseAndEscape(i::Handle<i::String>::cast(value))); |
} |
+namespace { |
+int GetSmiValue(i::Handle<i::FixedArray> array, int index) { |
+ return i::Smi::cast(array->get(index))->value(); |
+} |
+} // namespace |
+ |
+bool DebugInterface::Script::GetPossibleBreakpoints( |
+ const Location& start, const Location& end, |
+ std::vector<Location>* locations) const { |
+ CHECK(!start.IsEmpty()); |
+ i::Handle<i::Script> script = Utils::OpenHandle(this); |
+ |
+ i::Script::InitLineEnds(script); |
+ CHECK(script->line_ends()->IsFixedArray()); |
+ i::Isolate* isolate = script->GetIsolate(); |
+ i::Handle<i::FixedArray> line_ends = |
+ i::Handle<i::FixedArray>::cast(i::handle(script->line_ends(), isolate)); |
+ CHECK(line_ends->length()); |
+ |
+ int start_offset = GetSourcePosition(start); |
+ int end_offset; |
+ if (end.IsEmpty()) { |
+ end_offset = GetSmiValue(line_ends, line_ends->length() - 1) + 1; |
+ } else { |
+ end_offset = GetSourcePosition(end); |
+ } |
+ if (start_offset >= end_offset) return true; |
+ |
+ std::set<int> offsets; |
+ if (!isolate->debug()->GetPossibleBreakpoints(script, start_offset, |
+ end_offset, &offsets)) { |
+ return false; |
+ } |
+ |
+ int current_line_end_index = 0; |
+ for (const auto& it : offsets) { |
+ int offset = it; |
+ while (offset > GetSmiValue(line_ends, current_line_end_index)) { |
+ ++current_line_end_index; |
+ CHECK(current_line_end_index < line_ends->length()); |
+ } |
+ int line_offset = 0; |
+ |
+ if (current_line_end_index > 0) { |
+ line_offset = GetSmiValue(line_ends, current_line_end_index - 1) + 1; |
+ } |
+ locations->push_back(Location( |
+ current_line_end_index + script->line_offset(), |
+ offset - line_offset + |
+ (current_line_end_index == 0 ? script->column_offset() : 0))); |
+ } |
+ return true; |
+} |
+ |
+int DebugInterface::Script::GetSourcePosition(const Location& location) const { |
+ i::Handle<i::Script> script = Utils::OpenHandle(this); |
+ |
+ int line = std::max(location.GetLineNumber() - script->line_offset(), 0); |
+ int column = location.GetColumnNumber(); |
+ if (line == 0) { |
+ column = std::max(0, column - script->column_offset()); |
+ } |
+ |
+ i::Script::InitLineEnds(script); |
+ CHECK(script->line_ends()->IsFixedArray()); |
+ i::Handle<i::FixedArray> line_ends = i::Handle<i::FixedArray>::cast( |
+ i::handle(script->line_ends(), script->GetIsolate())); |
+ CHECK(line_ends->length()); |
+ if (line >= line_ends->length()) |
+ return GetSmiValue(line_ends, line_ends->length() - 1); |
+ int line_offset = GetSmiValue(line_ends, line); |
+ if (line == 0) return std::min(column, line_offset); |
+ int prev_line_offset = GetSmiValue(line_ends, line - 1); |
+ return std::min(prev_line_offset + column + 1, line_offset); |
+} |
+ |
MaybeLocal<DebugInterface::Script> DebugInterface::Script::Wrap( |
v8::Isolate* v8_isolate, v8::Local<v8::Object> script) { |
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(v8_isolate); |
@@ -8968,6 +9044,28 @@ MaybeLocal<DebugInterface::Script> DebugInterface::Script::Wrap( |
handle_scope.CloseAndEscape(script_obj)); |
} |
+DebugInterface::Location::Location(int lineNumber, int columnNumber) |
+ : lineNumber_(lineNumber), columnNumber_(columnNumber) { |
+ CHECK(lineNumber >= 0); |
+ CHECK(columnNumber >= 0); |
+} |
+ |
+DebugInterface::Location::Location() : lineNumber_(-1), columnNumber_(-1) {} |
+ |
+int DebugInterface::Location::GetLineNumber() const { |
+ CHECK(lineNumber_ >= 0); |
+ return lineNumber_; |
+} |
+ |
+int DebugInterface::Location::GetColumnNumber() const { |
+ CHECK(columnNumber_ >= 0); |
+ return columnNumber_; |
+} |
+ |
+bool DebugInterface::Location::IsEmpty() const { |
+ return lineNumber_ == -1 && columnNumber_ == -1; |
+} |
+ |
void DebugInterface::GetLoadedScripts( |
v8::Isolate* v8_isolate, |
PersistentValueVector<DebugInterface::Script>& scripts) { |