10#include "../../third_party/inspector_protocol/crdtp/json.h"
20#include "src/inspector/protocol/Debugger.h"
21#include "src/inspector/protocol/Protocol.h"
37using protocol::Debugger::BreakpointId;
38using protocol::Debugger::CallFrame;
39using protocol::Debugger::Scope;
40using protocol::Runtime::ExceptionDetails;
41using protocol::Runtime::RemoteObject;
42using protocol::Runtime::ScriptId;
44namespace InstrumentationEnum =
45 protocol::Debugger::SetInstrumentationBreakpoint::InstrumentationEnum;
47namespace DebuggerAgentState {
71 "Can only perform operation while paused.";
79#if V8_ENABLE_WEBASSEMBLY
87static constexpr size_t kWasmBytecodeMaxLength =
89static constexpr const char kWasmBytecodeExceedsTransferLimit[] =
90 "WebAssembly bytecode exceeds the transfer limit";
95enum class BreakpointType {
103 kInstrumentationBreakpoint
106String16 generateBreakpointId(BreakpointType type,
107 const String16& scriptSelector,
int lineNumber,
116 builder.
append(scriptSelector);
120String16 generateBreakpointId(BreakpointType type,
129String16 generateInstrumentationBreakpointId(
const String16& instrumentation) {
132 static_cast<int>(BreakpointType::kInstrumentationBreakpoint));
134 builder.
append(instrumentation);
138bool parseBreakpointId(
const String16& breakpointId, BreakpointType* type,
140 int* lineNumber =
nullptr,
int* columnNumber =
nullptr) {
141 size_t typeLineSeparator = breakpointId.
find(
':');
145 if (rawType <
static_cast<int>(BreakpointType::kByUrl) ||
146 rawType >
static_cast<int>(BreakpointType::kInstrumentationBreakpoint)) {
149 if (type) *type =
static_cast<BreakpointType
>(rawType);
150 if (rawType ==
static_cast<int>(BreakpointType::kDebugCommand) ||
151 rawType ==
static_cast<int>(BreakpointType::kMonitorCommand) ||
152 rawType ==
static_cast<int>(BreakpointType::kBreakpointAtEntry) ||
153 rawType ==
static_cast<int>(BreakpointType::kInstrumentationBreakpoint)) {
158 size_t lineColumnSeparator = breakpointId.
find(
':', typeLineSeparator + 1);
160 size_t columnSelectorSeparator =
161 breakpointId.
find(
':', lineColumnSeparator + 1);
163 if (scriptSelector) {
164 *scriptSelector = breakpointId.
substring(columnSelectorSeparator + 1);
167 *lineNumber = breakpointId
169 lineColumnSeparator - typeLineSeparator - 1)
176 columnSelectorSeparator - lineColumnSeparator - 1)
182bool positionComparator(
const std::pair<int, int>& a,
183 const std::pair<int, int>& b) {
184 if (a.first != b.first)
return a.first < b.first;
185 return a.second < b.second;
188std::unique_ptr<protocol::DictionaryValue> breakpointHint(
190 int breakpointColumnNumber,
int actualLineNumber,
int actualColumnNumber) {
192 int breakpointOffset;
193 if (!script.offset(actualLineNumber, actualColumnNumber).To(&actualOffset) ||
194 !script.offset(breakpointLineNumber, breakpointColumnNumber)
195 .To(&breakpointOffset)) {
199 auto hintObject = protocol::DictionaryValue::create();
201 std::pair<size_t, size_t> offsetAndLength =
204 rawHint.
substring(offsetAndLength.first, offsetAndLength.second);
205 for (
size_t i = 0;
i < hint.
length(); ++
i) {
206 if (hint[
i] ==
'\r' || hint[
i] ==
'\n' || hint[
i] ==
';') {
217 if (breakpointOffset <= actualOffset) {
218 size_t length = actualOffset - breakpointOffset + offsetAndLength.first;
219 String16 prefix = script.source(breakpointOffset, length);
223 v8::base::checked_cast<int32_t>(length));
229 const protocol::DictionaryValue* hintObject,
230 int* lineNumber,
int* columnNumber) {
231 if (*lineNumber < script.startLine() || *lineNumber > script.endLine())
233 if (*lineNumber == script.startLine() &&
234 *columnNumber < script.startColumn()) {
237 if (*lineNumber == script.endLine() && script.endColumn() < *columnNumber) {
242 if (!script.offset(*lineNumber, *columnNumber).To(&sourceOffset))
return;
244 int prefixLength = 0;
252 intptr_t searchRegionOffset = std::max(
254 size_t offset = sourceOffset - searchRegionOffset;
255 size_t searchRegionSize =
257 static_cast<intptr_t
>(prefixLength + hint.
length()));
259 String16 searchArea = script.source(searchRegionOffset, searchRegionSize);
271 static_cast<int>(searchRegionOffset +
offset + prefixLength));
277 size_t nextMatch = searchArea.
find(hint,
offset);
285 bestMatch = prevMatch;
287 bestMatch = nextMatch;
289 bestMatch = nextMatch -
offset <
offset - prevMatch ? nextMatch : prevMatch;
291 bestMatch += searchRegionOffset;
293 script.location(
static_cast<int>(bestMatch));
294 if (hintPosition.
IsEmpty())
return;
302 return protocol::Debugger::BreakLocation::TypeEnum::Call;
304 return protocol::Debugger::BreakLocation::TypeEnum::Return;
306 return protocol::Debugger::BreakLocation::TypeEnum::DebuggerStatement;
316 return Scope::TypeEnum::Global;
318 return Scope::TypeEnum::Local;
320 return Scope::TypeEnum::With;
322 return Scope::TypeEnum::Closure;
324 return Scope::TypeEnum::Catch;
326 return Scope::TypeEnum::Block;
328 return Scope::TypeEnum::Script;
330 return Scope::TypeEnum::Eval;
332 return Scope::TypeEnum::Module;
334 return Scope::TypeEnum::WasmExpressionStack;
341 std::unique_ptr<Array<Scope>>* scopes) {
342 *scopes = std::make_unique<Array<Scope>>();
343 if (!injectedScript)
return Response::Success();
344 if (iterator->
Done())
return Response::Success();
349 std::unique_ptr<RemoteObject> object;
355 auto scope = Scope::create()
356 .setType(scopeType(iterator->
GetType()))
357 .setObject(std::move(
object))
362 if (!name.isEmpty()) scope->setName(name);
366 scope->setStartLocation(protocol::Debugger::Location::create()
367 .setScriptId(scriptId)
368 .setLineNumber(
start.GetLineNumber())
369 .setColumnNumber(
start.GetColumnNumber())
373 scope->setEndLocation(protocol::Debugger::Location::create()
374 .setScriptId(scriptId)
375 .setLineNumber(
end.GetLineNumber())
376 .setColumnNumber(
end.GetColumnNumber())
379 (*scopes)->emplace_back(std::move(scope));
381 return Response::Success();
384protocol::DictionaryValue* getOrCreateObject(protocol::DictionaryValue*
object,
386 protocol::DictionaryValue* value =
object->getObject(
key);
387 if (value)
return value;
388 std::unique_ptr<protocol::DictionaryValue> newDictionary =
389 protocol::DictionaryValue::create();
390 value = newDictionary.get();
391 object->setObject(
key, std::move(newDictionary));
395Response isValidPosition(protocol::Debugger::ScriptPosition*
position) {
397 return Response::ServerError(
"Position missing 'line' or 'line' < 0.");
398 if (
position->getColumnNumber() < 0)
399 return Response::ServerError(
"Position missing 'column' or 'column' < 0.");
400 return Response::Success();
403Response isValidRangeOfPositions(
404 const std::vector<std::pair<int, int>>& positions) {
405 for (
size_t i = 1;
i < positions.
size(); ++
i) {
406 if (positions[
i - 1].first < positions[
i].first)
continue;
407 if (positions[
i - 1].first == positions[
i].first &&
410 return Response::ServerError(
411 "Input positions array is not sorted or contains duplicate values.");
413 return Response::Success();
429 protocol::DictionaryValue* state)
433 m_enableState(kDisabled),
445 std::vector<std::unique_ptr<V8DebuggerScript>> compiledScripts =
447 for (
auto& script : compiledScripts) {
466 return Response::ServerError(
"Debugger is stopping");
468 maxScriptsCacheSize.value_or(std::numeric_limits<double>::max()));
473 if (
enabled())
return Response::Success();
476 return Response::ServerError(
"Script execution is prohibited");
479 return Response::Success();
483 if (!
enabled())
return Response::Success();
523 return Response::Success();
535 double maxScriptCacheSize = 0;
537 &maxScriptCacheSize);
547 int asyncCallStackDepth = 0;
549 &asyncCallStackDepth);
563 if (!
enabled())
return Response::Success();
571 return Response::Success();
577 return Response::Success();
587 if (type == BreakpointType::kByUrlRegex) {
588 regex_ = std::make_unique<V8Regex>(inspector, selector,
true);
592 bool matches(
const V8DebuggerScript& script) {
594 case BreakpointType::kByUrl:
596 case BreakpointType::kByScriptHash:
598 case BreakpointType::kByUrlRegex: {
599 return regex_->match(script.sourceURL()) != -1;
601 case BreakpointType::kByScriptId: {
618 int lineNumber, std::optional<String16> optionalURL,
619 std::optional<String16> optionalURLRegex,
620 std::optional<String16> optionalScriptHash,
621 std::optional<int> optionalColumnNumber,
622 std::optional<String16> optionalCondition,
String16* outBreakpointId,
623 std::unique_ptr<protocol::Array<protocol::Debugger::Location>>* locations) {
626 *locations = std::make_unique<Array<protocol::Debugger::Location>>();
628 int specified = (optionalURL.has_value() ? 1 : 0) +
629 (optionalURLRegex.has_value() ? 1 : 0) +
630 (optionalScriptHash.has_value() ? 1 : 0);
631 if (specified != 1) {
632 return Response::ServerError(
633 "Either url or urlRegex or scriptHash must be specified.");
635 int columnNumber = 0;
636 if (optionalColumnNumber.has_value()) {
637 columnNumber = optionalColumnNumber.value();
638 if (columnNumber < 0)
639 return Response::ServerError(
"Incorrect column number");
642 BreakpointType type = BreakpointType::kByUrl;
644 if (optionalURLRegex.has_value()) {
645 selector = optionalURLRegex.value();
646 type = BreakpointType::kByUrlRegex;
647 }
else if (optionalURL.has_value()) {
648 selector = optionalURL.value();
649 type = BreakpointType::kByUrl;
650 }
else if (optionalScriptHash.has_value()) {
651 selector = optionalScriptHash.value();
652 type = BreakpointType::kByScriptHash;
660 generateBreakpointId(type, selector, lineNumber, columnNumber);
661 protocol::DictionaryValue* breakpoints;
663 case BreakpointType::kByUrlRegex:
667 case BreakpointType::kByUrl:
668 breakpoints = getOrCreateObject(
672 case BreakpointType::kByScriptHash:
673 breakpoints = getOrCreateObject(
681 if (breakpoints->get(breakpointId)) {
682 return Response::ServerError(
683 "Breakpoint at specified location already exists.");
686 std::unique_ptr<protocol::DictionaryValue> hint;
688 if (!matcher.matches(*script.second))
continue;
692 int adjustedLineNumber = lineNumber;
693 int adjustedColumnNumber = columnNumber;
695 adjustBreakpointLocation(*script.second, hint.get(), &adjustedLineNumber,
696 &adjustedColumnNumber);
698 std::unique_ptr<protocol::Debugger::Location> location =
700 adjustedLineNumber, adjustedColumnNumber);
701 if (location && type != BreakpointType::kByUrlRegex) {
702 hint = breakpointHint(*script.second, lineNumber, columnNumber,
703 location->getLineNumber(),
704 location->getColumnNumber(adjustedColumnNumber));
706 if (location) (*locations)->emplace_back(std::move(location));
708 breakpoints->setString(breakpointId,
condition);
710 protocol::DictionaryValue* breakpointHints =
712 breakpointHints->setObject(breakpointId, std::move(hint));
714 *outBreakpointId = breakpointId;
715 return Response::Success();
719 std::unique_ptr<protocol::Debugger::Location> location,
720 std::optional<String16> optionalCondition,
String16* outBreakpointId,
721 std::unique_ptr<protocol::Debugger::Location>* actualLocation) {
722 String16 breakpointId = generateBreakpointId(
723 BreakpointType::kByScriptId, location->getScriptId(),
724 location->getLineNumber(), location->getColumnNumber(0));
729 return Response::ServerError(
730 "Breakpoint at specified location already exists.");
733 optionalCondition.value_or(
String16()),
734 location->getLineNumber(),
735 location->getColumnNumber(0));
736 if (!*actualLocation)
737 return Response::ServerError(
"Could not resolve breakpoint");
738 *outBreakpointId = breakpointId;
739 return Response::Success();
743 const String16& functionObjectId, std::optional<String16> optionalCondition,
749 if (!response.IsSuccess())
return response;
751 return Response::ServerError(
"Could not find function with given id");
756 generateBreakpointId(BreakpointType::kBreakpointAtEntry, function);
759 return Response::ServerError(
760 "Breakpoint at specified location already exists.");
765 *outBreakpointId = breakpointId;
766 return Response::Success();
772 String16 breakpointId = generateInstrumentationBreakpointId(instrumentation);
773 protocol::DictionaryValue* breakpoints = getOrCreateObject(
775 if (breakpoints->get(breakpointId)) {
776 return Response::ServerError(
777 "Instrumentation breakpoint is already enabled.");
779 breakpoints->setBoolean(breakpointId,
true);
780 *outBreakpointId = breakpointId;
781 return Response::Success();
788 if (!parseBreakpointId(breakpointId, &type, &selector)) {
789 return Response::Success();
792 protocol::DictionaryValue* breakpoints =
nullptr;
794 case BreakpointType::kByUrl: {
795 protocol::DictionaryValue* breakpointsByUrl =
797 if (breakpointsByUrl) {
798 breakpoints = breakpointsByUrl->getObject(selector);
801 case BreakpointType::kByScriptHash: {
802 protocol::DictionaryValue* breakpointsByScriptHash =
804 if (breakpointsByScriptHash) {
805 breakpoints = breakpointsByScriptHash->getObject(selector);
808 case BreakpointType::kByUrlRegex:
811 case BreakpointType::kInstrumentationBreakpoint:
818 if (breakpoints) breakpoints->remove(breakpointId);
819 protocol::DictionaryValue* breakpointHints =
821 if (breakpointHints) breakpointHints->remove(breakpointId);
826 std::vector<V8DebuggerScript*> scripts;
827 for (
const auto& scriptIter :
m_scripts) {
828 const bool scriptSelectorMatch = matcher.matches(*scriptIter.second);
832 const bool isInstrumentation =
833 type == BreakpointType::kInstrumentationBreakpoint;
834 if (!scriptSelectorMatch && !isInstrumentation)
continue;
837 scripts.push_back(script);
842 return Response::Success();
847 const std::vector<V8DebuggerScript*>& scripts) {
849 BreakpointIdToDebuggerBreakpointIdsMap::iterator
850 debuggerBreakpointIdsIterator =
852 if (debuggerBreakpointIdsIterator ==
856 for (
const auto&
id : debuggerBreakpointIdsIterator->second) {
857#if V8_ENABLE_WEBASSEMBLY
858 for (
auto& script : scripts) {
859 script->removeWasmBreakpoint(
id);
869 std::unique_ptr<protocol::Debugger::Location>
start,
870 std::unique_ptr<protocol::Debugger::Location>
end,
871 std::optional<bool> restrictToFunction,
872 std::unique_ptr<protocol::Array<protocol::Debugger::BreakLocation>>*
876 if (
start->getLineNumber() < 0 ||
start->getColumnNumber(0) < 0)
877 return Response::ServerError(
878 "start.lineNumber and start.columnNumber should be >= 0");
881 start->getColumnNumber(0));
884 if (
end->getScriptId() != scriptId)
885 return Response::ServerError(
886 "Locations should contain the same scriptId");
887 int line =
end->getLineNumber();
888 int column =
end->getColumnNumber(0);
889 if (line < 0 || column < 0)
890 return Response::ServerError(
891 "end.lineNumber and end.columnNumber should be >= 0");
895 if (it ==
m_scripts.end())
return Response::ServerError(
"Script not found");
896 std::vector<v8::debug::BreakLocation> v8Locations;
899 int contextId = it->second->executionContextId();
902 return Response::ServerError(
"Cannot retrive script context");
908 it->second->getPossibleBreakpoints(
909 v8Start, v8End, restrictToFunction.value_or(
false), &v8Locations);
913 std::make_unique<protocol::Array<protocol::Debugger::BreakLocation>>();
917 const size_t numBreakpointsToSend =
919 for (
size_t i = 0;
i < numBreakpointsToSend; ++
i) {
920 std::unique_ptr<protocol::Debugger::BreakLocation> breakLocation =
921 protocol::Debugger::BreakLocation::create()
922 .setScriptId(scriptId)
923 .setLineNumber(v8Locations[
i].GetLineNumber())
924 .setColumnNumber(v8Locations[
i].GetColumnNumber())
927 breakLocation->setType(breakLocationType(v8Locations[
i].
type()));
929 (*locations)->emplace_back(std::move(breakLocation));
931 return Response::Success();
935 std::unique_ptr<protocol::Debugger::Location> location,
936 std::optional<String16> targetCallFrames) {
939 ScriptsMap::iterator it =
m_scripts.find(location->getScriptId());
941 return Response::ServerError(
"Cannot continue to specified location");
947 return Response::ServerError(
"Cannot continue to specified location");
952 targetCallFrames.value_or(
953 protocol::Debugger::ContinueToLocation::TargetCallFramesEnum::Any));
957 std::unique_ptr<protocol::Runtime::StackTraceId> inStackTraceId,
958 std::unique_ptr<protocol::Runtime::StackTrace>* outStackTrace) {
960 int64_t
id = inStackTraceId->getId().toInteger64(&isOk);
961 if (!isOk)
return Response::ServerError(
"Invalid stack trace id");
964 if (inStackTraceId->hasDebuggerId()) {
971 return Response::ServerError(
"Invalid stack trace id");
975 return Response::ServerError(
"Invalid stack trace id");
979 return Response::ServerError(
"Stack trace with given id is not found");
981 *outStackTrace = stack->buildInspectorObject(
983 return Response::Success();
989 ScriptsMap::iterator it =
m_scripts.find(scriptId);
994 const String16& scriptSourceURL = it->second->sourceURL();
1003 int contextId = it->second->executionContextId();
1013 const std::vector<std::pair<int, int>>& ranges =
1014 itBlackboxedPositions->second;
1015 auto itStartRange = std::lower_bound(
1016 ranges.begin(), ranges.end(),
1017 std::make_pair(
start.GetLineNumber(),
start.GetColumnNumber()),
1018 positionComparator);
1019 auto itEndRange = std::lower_bound(
1020 itStartRange, ranges.end(),
1021 std::make_pair(
end.GetLineNumber(),
end.GetColumnNumber()),
1022 positionComparator);
1026 return itStartRange == itEndRange &&
1027 std::distance(ranges.begin(), itStartRange) % 2;
1037 const std::vector<std::pair<int, int>>& ranges = it->second;
1039 const std::pair<int, int> location = std::make_pair(line, column);
1040 auto itLowerBound = std::lower_bound(ranges.begin(), ranges.end(), location,
1041 positionComparator);
1043 bool shouldSkip =
false;
1044 if (itLowerBound != ranges.end()) {
1049 const bool isSameAsLowerBound = location == *itLowerBound;
1050 const bool isUnevenIndex = (itLowerBound - ranges.begin()) % 2;
1051 shouldSkip = isSameAsLowerBound ^ isUnevenIndex;
1061std::unique_ptr<protocol::Debugger::Location>
1065 int lineNumber,
int columnNumber) {
1069 ScriptsMap::iterator scriptIterator =
m_scripts.find(scriptId);
1070 if (scriptIterator ==
m_scripts.end())
return nullptr;
1075 int contextId = script->executionContextId();
1077 if (!inspected)
return nullptr;
1081 if (!script->setBreakpoint(
condition, &location, &debuggerBreakpointId)) {
1088 debuggerBreakpointId);
1090 return protocol::Debugger::Location::create()
1091 .setScriptId(scriptId)
1102 &debuggerBreakpointId)) {
1107 debuggerBreakpointId);
1112 std::optional<bool> optionalCaseSensitive,
1113 std::optional<bool> optionalIsRegex,
1114 std::unique_ptr<Array<protocol::Debugger::SearchMatch>>* results) {
1116 ScriptsMap::iterator it =
m_scripts.find(scriptId);
1118 return Response::ServerError(
"No script for id: " + scriptId.
utf8());
1120 *results = std::make_unique<protocol::Array<protocol::Debugger::SearchMatch>>(
1122 optionalCaseSensitive.value_or(
false),
1123 optionalIsRegex.value_or(
false)));
1124 return Response::Success();
1131 return protocol::Debugger::SetScriptSource::StatusEnum::Ok;
1133 return protocol::Debugger::SetScriptSource::StatusEnum::CompileError;
1135 return protocol::Debugger::SetScriptSource::StatusEnum::
1136 BlockedByActiveFunction;
1138 return protocol::Debugger::SetScriptSource::StatusEnum::
1139 BlockedByActiveGenerator;
1141 return protocol::Debugger::SetScriptSource::StatusEnum::
1142 BlockedByTopLevelEsModuleChange;
1149 std::optional<bool> dryRun, std::optional<bool> allowTopFrameEditing,
1150 std::unique_ptr<protocol::Array<protocol::Debugger::CallFrame>>*
1152 std::optional<bool>* stackChanged,
1153 std::unique_ptr<protocol::Runtime::StackTrace>* asyncStackTrace,
1154 std::unique_ptr<protocol::Runtime::StackTraceId>* asyncStackTraceId,
1156 std::unique_ptr<protocol::Runtime::ExceptionDetails>* optOutCompileError) {
1159 ScriptsMap::iterator it =
m_scripts.find(scriptId);
1161 return Response::ServerError(
"No script with given id found");
1163 int contextId = it->second->executionContextId();
1166 return Response::InternalError();
1171 const bool allowTopFrameLiveEditing = allowTopFrameEditing.value_or(
false);
1174 it->second->setSource(newContent, dryRun.value_or(
false),
1175 allowTopFrameLiveEditing, &
result);
1176 *status = buildStatus(
result.status);
1178 *optOutCompileError =
1179 protocol::Runtime::ExceptionDetails::create()
1182 .setLineNumber(
result.line_number != -1 ?
result.line_number - 1
1184 .setColumnNumber(
result.column_number != -1 ?
result.column_number
1187 return Response::Success();
1190 if (
result.restart_top_frame_required) {
1191 CHECK(allowTopFrameLiveEditing);
1199 return Response::Success();
1203 const String16& callFrameId, std::optional<String16> mode,
1204 std::unique_ptr<Array<CallFrame>>* newCallFrames,
1205 std::unique_ptr<protocol::Runtime::StackTrace>* asyncStackTrace,
1206 std::unique_ptr<protocol::Runtime::StackTraceId>* asyncStackTraceId) {
1208 if (!mode.has_value()) {
1209 return Response::ServerError(
1210 "Restarting frame without 'mode' not supported");
1212 if (mode.value() != protocol::Debugger::RestartFrame::ModeEnum::StepInto) {
1213 return Response::InvalidParams(
"'StepInto' is the only valid mode");
1218 if (!response.IsSuccess())
return response;
1219 int callFrameOrdinal =
static_cast<int>(scope.
frameOrdinal());
1222 callFrameOrdinal)) {
1223 return Response::ServerError(
"Restarting frame failed");
1226 *newCallFrames = std::make_unique<Array<CallFrame>>();
1227 return Response::Success();
1232 std::optional<protocol::Binary>* bytecode) {
1234 ScriptsMap::iterator it =
m_scripts.find(scriptId);
1236 auto cachedScriptIt =
1239 return cachedScript.scriptId == scriptId;
1242 *scriptSource = cachedScriptIt->source;
1244 cachedScriptIt->bytecode.begin(), cachedScriptIt->bytecode.size()));
1245 return Response::Success();
1247 return Response::ServerError(
"No script for id: " + scriptId.
utf8());
1249 *scriptSource = it->second->source(0);
1250#if V8_ENABLE_WEBASSEMBLY
1252 if (it->second->wasmBytecode().To(&span)) {
1253 if (span.size() > kWasmBytecodeMaxLength) {
1254 return Response::ServerError(kWasmBytecodeExceedsTransferLimit);
1259 return Response::Success();
1273 lines.reserve(size);
1283 if (count == 0)
return;
1286 for (
size_t i = 0;
i < num_chunks - 1;
i++) {
1289 size_t last = num_chunks - 1;
1292 chunks_[last].Reserve(last_size);
1296 uint32_t bytecode_offset)
override {
1299 static_cast<int>(bytecode_offset));
1326 const String16& in_scriptId, std::optional<String16>* out_streamId,
1327 int* out_totalNumberOfLines,
1328 std::unique_ptr<protocol::Array<int>>* out_functionBodyOffsets,
1329 std::unique_ptr<protocol::Debugger::WasmDisassemblyChunk>* out_chunk) {
1330#if V8_ENABLE_WEBASSEMBLY
1332 ScriptsMap::iterator it =
m_scripts.find(in_scriptId);
1333 std::unique_ptr<DisassemblyCollectorImpl> collector =
1334 std::make_unique<DisassemblyCollectorImpl>();
1335 std::vector<int> functionBodyOffsets;
1339 return Response::InvalidParams(
"Script with id " + in_scriptId.
utf8() +
1340 " is not WebAssembly");
1342 script->Disassemble(collector.get(), &functionBodyOffsets);
1344 auto cachedScriptIt =
1347 return cachedScript.scriptId == in_scriptId;
1350 return Response::InvalidParams(
"No script for id: " + in_scriptId.
utf8());
1353 collector.get(), &functionBodyOffsets);
1355 *out_totalNumberOfLines =
1356 static_cast<int>(collector->total_number_of_lines());
1357 *out_functionBodyOffsets =
1358 std::make_unique<protocol::Array<int>>(std::move(functionBodyOffsets));
1360 DCHECK(collector->HasNextChunk());
1362 *out_chunk = protocol::Debugger::WasmDisassemblyChunk::create()
1363 .setBytecodeOffsets(std::make_unique<protocol::Array<int>>(
1365 .setLines(std::make_unique<protocol::Array<String16>>(
1366 std::move(chunk.
lines)))
1368 if (collector->HasNextChunk()) {
1370 *out_streamId = streamId;
1373 return Response::Success();
1375 return Response::ServerError(
"WebAssembly is disabled");
1381 std::unique_ptr<protocol::Debugger::WasmDisassemblyChunk>* out_chunk) {
1382#if V8_ENABLE_WEBASSEMBLY
1386 return Response::InvalidParams(
"No chunks available for stream " +
1387 in_streamId.
utf8());
1389 if (it->second->HasNextChunk()) {
1391 *out_chunk = protocol::Debugger::WasmDisassemblyChunk::create()
1392 .setBytecodeOffsets(std::make_unique<protocol::Array<int>>(
1394 .setLines(std::make_unique<protocol::Array<String16>>(
1395 std::move(chunk.
lines)))
1399 protocol::Debugger::WasmDisassemblyChunk::create()
1400 .setBytecodeOffsets(std::make_unique<protocol::Array<int>>())
1401 .setLines(std::make_unique<protocol::Array<String16>>())
1405 return Response::Success();
1407 return Response::ServerError(
"WebAssembly is disabled");
1413#if V8_ENABLE_WEBASSEMBLY
1415 ScriptsMap::iterator it =
m_scripts.find(scriptId);
1417 return Response::ServerError(
"No script for id: " + scriptId.
utf8());
1419 if (!it->second->wasmBytecode().To(&span))
1420 return Response::ServerError(
"Script with id " + scriptId.
utf8() +
1421 " is not WebAssembly");
1422 if (span.size() > kWasmBytecodeMaxLength) {
1423 return Response::ServerError(kWasmBytecodeExceedsTransferLimit);
1426 return Response::Success();
1428 return Response::ServerError(
"WebAssembly is disabled");
1434 std::unique_ptr<protocol::DictionaryValue> breakAuxData) {
1435 m_breakReason.push_back(std::make_pair(breakReason, std::move(breakAuxData)));
1444 std::vector<BreakReason> emptyBreakReason;
1450 std::unique_ptr<protocol::DictionaryValue> data) {
1476 return Response::Success();
1484 return Response::Success();
1493 terminateOnResume.value_or(
false));
1494 return Response::Success();
1498 std::unique_ptr<protocol::Array<protocol::Debugger::LocationRange>>
1504 if (res.IsError())
return res;
1511 return Response::Success();
1515 std::optional<bool> inBreakOnAsyncCall,
1516 std::unique_ptr<protocol::Array<protocol::Debugger::LocationRange>>
1522 if (res.IsError())
return res;
1529 inBreakOnAsyncCall.value_or(
false));
1530 return Response::Success();
1537 return Response::Success();
1541 std::unique_ptr<protocol::Runtime::StackTraceId> inParentStackTraceId) {
1543 return Response::Success();
1547 const String16& stringPauseState) {
1550 if (stringPauseState ==
"none") {
1552 }
else if (stringPauseState ==
"all") {
1554 }
else if (stringPauseState ==
"caught") {
1556 }
else if (stringPauseState ==
"uncaught") {
1559 return Response::ServerError(
"Unknown pause on exceptions mode: " +
1560 stringPauseState.
utf8());
1563 return Response::Success();
1576 std::optional<String16> objectGroup,
1577 std::optional<bool> includeCommandLineAPI, std::optional<bool> silent,
1578 std::optional<bool> returnByValue, std::optional<bool> generatePreview,
1579 std::optional<bool> throwOnSideEffect, std::optional<double> timeout,
1580 std::unique_ptr<RemoteObject>*
result,
1581 std::unique_ptr<protocol::Runtime::ExceptionDetails>* exceptionDetails) {
1585 if (!response.IsSuccess())
return response;
1589 int frameOrdinal =
static_cast<int>(scope.
frameOrdinal());
1592 return Response::ServerError(
"Could not find call frame with given id");
1598 if (timeout.has_value()) {
1599 response = evaluateScope.
setTimeout(timeout.value() / 1000.0);
1600 if (!response.IsSuccess())
return response;
1603 throwOnSideEffect.value_or(
false));
1608 if (!response.IsSuccess())
return response;
1609 WrapOptions wrapOptions = generatePreview.value_or(
false)
1612 if (returnByValue.value_or(
false))
1615 maybeResultValue, scope.
tryCatch(), objectGroup.value_or(
""), wrapOptions,
1616 throwOnSideEffect.value_or(
false),
result, exceptionDetails);
1620 int scopeNumber,
const String16& variableName,
1621 std::unique_ptr<protocol::Runtime::CallArgument> newValueArgument,
1627 if (!response.IsSuccess())
return response;
1631 if (!response.IsSuccess())
return response;
1633 int frameOrdinal =
static_cast<int>(scope.
frameOrdinal());
1636 return Response::ServerError(
"Could not find call frame with given id");
1638 auto scopeIterator = it->GetScopeIterator();
1639 while (!scopeIterator->Done() && scopeNumber > 0) {
1641 scopeIterator->Advance();
1643 if (scopeNumber != 0) {
1644 return Response::ServerError(
"Could not find scope with given number");
1650 return Response::InternalError();
1652 return Response::Success();
1656 std::unique_ptr<protocol::Runtime::CallArgument> protocolNewValue) {
1661 if (iterator->Done()) {
1662 return Response::ServerError(
"Could not find top call frame");
1664 if (iterator->GetReturnValue().IsEmpty()) {
1665 return Response::ServerError(
1666 "Could not update return value at non-return position");
1670 if (!response.IsSuccess())
return response;
1674 if (!response.IsSuccess())
return response;
1676 return Response::Success();
1685 return Response::Success();
1689 std::unique_ptr<protocol::Array<String16>> patterns,
1690 std::optional<bool> skipAnonymous) {
1694 if (patterns->empty()) {
1698 return Response::Success();
1702 patternBuilder.
append(
'(');
1703 for (
size_t i = 0;
i < patterns->
size() - 1; ++
i) {
1704 patternBuilder.
append((*patterns)[
i]);
1705 patternBuilder.
append(
"|");
1707 patternBuilder.
append(patterns->back());
1708 patternBuilder.
append(
')');
1711 if (!response.IsSuccess())
return response;
1714 return Response::Success();
1718 std::unique_ptr<protocol::Array<String16>> uniqueIds) {
1720 for (
const String16& uniqueId : *uniqueIds) {
1723 return Response::Success();
1727 std::unique_ptr<V8Regex> regex(
new V8Regex(
1729 if (!regex->isValid())
1730 return Response::ServerError(
"Pattern parser error: " +
1731 regex->errorMessage().utf8());
1733 return Response::Success();
1738 it.second->resetBlackboxedStateCache();
1744 std::unique_ptr<protocol::Array<protocol::Debugger::ScriptPosition>>
1748 return Response::ServerError(
"No script with passed id.");
1750 if (inPositions->empty()) {
1752 it->second->resetBlackboxedStateCache();
1753 return Response::Success();
1756 std::vector<std::pair<int, int>> positions;
1757 positions.reserve(inPositions->size());
1758 for (
const std::unique_ptr<protocol::Debugger::ScriptPosition>&
position :
1760 Response res = isValidPosition(
position.get());
1761 if (res.IsError())
return res;
1763 positions.push_back(
1766 Response res = isValidRangeOfPositions(positions);
1767 if (res.IsError())
return res;
1770 it->second->resetBlackboxedStateCache();
1771 return Response::Success();
1775 std::unique_ptr<Array<CallFrame>>*
result) {
1777 *
result = std::make_unique<Array<CallFrame>>();
1778 return Response::Success();
1781 *
result = std::make_unique<Array<CallFrame>>();
1783 int frameOrdinal = 0;
1784 for (; !iterator->Done(); iterator->Advance(), frameOrdinal++) {
1785 int contextId = iterator->GetContextId();
1793 std::unique_ptr<Array<Scope>> scopes;
1794 auto scopeIterator = iterator->GetScopeIterator();
1796 buildScopes(
m_isolate, scopeIterator.get(), injectedScript, &scopes);
1797 if (!res.IsSuccess())
return res;
1799 std::unique_ptr<RemoteObject> protocolReceiver;
1800 if (injectedScript) {
1802 if (iterator->GetReceiver().ToLocal(&
receiver)) {
1806 if (!res.IsSuccess())
return res;
1809 if (!protocolReceiver) {
1810 protocolReceiver = RemoteObject::create()
1811 .setType(RemoteObject::TypeEnum::Undefined)
1816 DCHECK(!script.IsEmpty());
1817 std::unique_ptr<protocol::Debugger::Location> location =
1818 protocol::Debugger::Location::create()
1824 auto frame = CallFrame::create()
1825 .setCallFrameId(callFrameId)
1827 m_isolate, iterator->GetFunctionDebugName()))
1828 .setLocation(std::move(location))
1830 .setScopeChain(std::move(scopes))
1831 .setThis(std::move(protocolReceiver))
1832 .setCanBeRestarted(iterator->CanBeRestarted())
1837 frame->setFunctionLocation(
1838 protocol::Debugger::Location::create()
1846 if (!returnValue.
IsEmpty() && injectedScript) {
1847 std::unique_ptr<RemoteObject>
value;
1851 if (!res.IsSuccess())
return res;
1852 frame->setReturnValue(std::move(value));
1854 (*result)->emplace_back(std::move(frame));
1856 return Response::Success();
1859std::unique_ptr<protocol::Runtime::StackTrace>
1861 std::shared_ptr<AsyncStackTrace> asyncParent =
1863 if (!asyncParent)
return nullptr;
1864 return asyncParent->buildInspectorObject(
1868std::unique_ptr<protocol::Runtime::StackTraceId>
1871 if (externalParent.
IsInvalid())
return nullptr;
1872 return protocol::Runtime::StackTraceId::create()
1884 switch (script.getLanguage()) {
1886 return protocol::Debugger::ScriptLanguageEnum::WebAssembly;
1888 return protocol::Debugger::ScriptLanguageEnum::JavaScript;
1892#if V8_ENABLE_WEBASSEMBLY
1893static const char* getDebugSymbolTypeName(
1894 v8::debug::WasmScript::DebugSymbols::Type type) {
1896 case v8::debug::WasmScript::DebugSymbols::Type::SourceMap:
1897 return v8_inspector::protocol::Debugger::DebugSymbols::TypeEnum::
1899 case v8::debug::WasmScript::DebugSymbols::Type::EmbeddedDWARF:
1900 return v8_inspector::protocol::Debugger::DebugSymbols::TypeEnum::
1902 case v8::debug::WasmScript::DebugSymbols::Type::ExternalDWARF:
1903 return v8_inspector::protocol::Debugger::DebugSymbols::TypeEnum::
1908static void getDebugSymbols(
1909 const V8DebuggerScript& script,
1910 std::unique_ptr<Array<protocol::Debugger::DebugSymbols>>* debug_symbols) {
1911 std::vector<v8::debug::WasmScript::DebugSymbols> v8_script_debug_symbols =
1912 script.getDebugSymbols();
1914 *debug_symbols = std::make_unique<Array<protocol::Debugger::DebugSymbols>>();
1915 for (
size_t i = 0;
i < v8_script_debug_symbols.size(); ++
i) {
1916 v8::debug::WasmScript::DebugSymbols& symbol = v8_script_debug_symbols[
i];
1917 std::unique_ptr<protocol::Debugger::DebugSymbols> protocolDebugSymbol =
1918 v8_inspector::protocol::Debugger::DebugSymbols::create()
1919 .setType(getDebugSymbolTypeName(symbol.type))
1921 if (symbol.external_url.size() > 0) {
1922 protocolDebugSymbol->setExternalURL(
1923 String16(symbol.external_url.data(), symbol.external_url.size()));
1925 (*debug_symbols)->emplace_back(std::move(protocolDebugSymbol));
1932class DeferredMakeWeakScope {
1934 explicit DeferredMakeWeakScope(V8DebuggerScript& script) :
script_(script) {}
1936 ~DeferredMakeWeakScope() {
script_.MakeWeak(); }
1945 std::unique_ptr<V8DebuggerScript> script,
bool success) {
1948 String16 scriptSource = script->source(0);
1953 int contextId = script->executionContextId();
1957 std::unique_ptr<protocol::DictionaryValue> executionContextAuxData;
1962 std::vector<uint8_t> cbor;
1963 v8_crdtp::json::ConvertJSONToCBOR(
1965 executionContextAuxData = protocol::DictionaryValue::cast(
1966 protocol::Value::parseBinary(cbor.data(), cbor.size()));
1968 bool isLiveEdit = script->isLiveEdit();
1969 bool hasSourceURLComment = script->hasSourceURLComment();
1970 bool isModule = script->isModule();
1971 String16 scriptId = script->scriptId();
1972 String16 scriptURL = script->sourceURL();
1973 String16 embedderName = script->embedderName();
1975 std::optional<int> codeOffset;
1976 std::unique_ptr<Array<protocol::Debugger::DebugSymbols>> debugSymbols;
1977#if V8_ENABLE_WEBASSEMBLY
1979 codeOffset = script->codeOffset();
1980 getDebugSymbols(*script, &debugSymbols);
1984 m_scripts[scriptId] = std::move(script);
1986 ScriptsMap::iterator scriptIterator =
m_scripts.find(scriptId);
1993 DeferredMakeWeakScope weak_scope(*scriptRef);
2002 const bool* isLiveEditParam = isLiveEdit ? &isLiveEdit :
nullptr;
2003 const bool* hasSourceURLParam =
2004 hasSourceURLComment ? &hasSourceURLComment :
nullptr;
2005 const bool* isModuleParam = isModule ? &isModule :
nullptr;
2006 std::unique_ptr<V8StackTraceImpl> stack =
2008 std::unique_ptr<protocol::Runtime::StackTrace> stackTrace =
2009 stack && !stack->isEmpty()
2010 ? stack->buildInspectorObjectImpl(
m_debugger, 0)
2018 std::move(executionContextAuxData), std::move(sourceMapURLParam),
2019 hasSourceURLParam, isModuleParam, scriptRef->
length(),
2020 std::move(stackTrace), std::move(codeOffset), std::move(scriptLanguage),
2025 std::vector<protocol::DictionaryValue*> potentialBreakpoints;
2027 protocol::DictionaryValue* breakpointsByUrl =
2029 if (breakpointsByUrl) {
2030 potentialBreakpoints.push_back(breakpointsByUrl->getObject(scriptURL));
2032 potentialBreakpoints.push_back(
2035 protocol::DictionaryValue* breakpointsByScriptHash =
2037 if (breakpointsByScriptHash) {
2038 potentialBreakpoints.push_back(
2039 breakpointsByScriptHash->getObject(scriptRef->
hash()));
2041 protocol::DictionaryValue* breakpointHints =
2043 std::map<String16, std::unique_ptr<protocol::Debugger::Location>>
2044 resolvedBreakpoints;
2045 for (
auto breakpoints : potentialBreakpoints) {
2046 if (!breakpoints)
continue;
2047 for (
size_t i = 0;
i < breakpoints->
size(); ++
i) {
2048 auto breakpointWithCondition = breakpoints->at(
i);
2049 String16 breakpointId = breakpointWithCondition.first;
2051 BreakpointType
type;
2054 int columnNumber = 0;
2055 parseBreakpointId(breakpointId, &type, &selector, &lineNumber,
2059 if (!matcher.matches(*scriptRef))
continue;
2064 breakpointWithCondition.second->asString(&
condition);
2065 protocol::DictionaryValue* hint =
2066 breakpointHints ? breakpointHints->getObject(breakpointId) :
nullptr;
2068 adjustBreakpointLocation(*scriptRef, hint, &lineNumber, &columnNumber);
2070 std::unique_ptr<protocol::Debugger::Location> location =
2074 resolvedBreakpoints.emplace(breakpointId, std::move(location));
2078 auto resolvedBreakpointObjects =
2079 !resolvedBreakpoints.empty()
2080 ? std::make_unique<std::vector<
2081 std::unique_ptr<protocol::Debugger::ResolvedBreakpoint>>>()
2083 for (
const auto& pair : resolvedBreakpoints) {
2084 resolvedBreakpointObjects->emplace_back(
2085 protocol::Debugger::ResolvedBreakpoint::create()
2086 .setBreakpointId(pair.first)
2087 .setLocation(pair.second->Clone())
2095 std::move(executionContextAuxData), isLiveEditParam,
2096 std::move(sourceMapURLParam), hasSourceURLParam, isModuleParam,
2097 scriptRef->
length(), std::move(stackTrace), std::move(codeOffset),
2098 std::move(scriptLanguage), std::move(debugSymbols), embedderName,
2099 std::move(resolvedBreakpointObjects));
2101 for (
auto& pair : resolvedBreakpoints) {
2102 m_frontend.breakpointResolved(pair.first, std::move(pair.second));
2110 protocol::DictionaryValue* breakpoints =
2112 if (!breakpoints)
return;
2116 if (isBlackboxed)
return;
2119 String16 breakpointId = generateInstrumentationBreakpointId(
2120 InstrumentationEnum::BeforeScriptExecution);
2121 if (!breakpoints->get(breakpointId)) {
2122 if (sourceMapURL.
isEmpty())
return;
2123 breakpointId = generateInstrumentationBreakpointId(
2124 InstrumentationEnum::BeforeScriptWithSourceMapExecution);
2125 if (!breakpoints->get(breakpointId))
return;
2132 debuggerBreakpointId);
2137 String16 breakReason = protocol::Debugger::Paused::ReasonEnum::Other;
2138 std::unique_ptr<protocol::DictionaryValue> breakAuxData;
2140 std::unique_ptr<Array<CallFrame>> protocolCallFrames;
2142 if (!response.IsSuccess())
2143 protocolCallFrames = std::make_unique<Array<CallFrame>>();
2147 DCHECK_GT(protocolCallFrames->size(), 0);
2148 if (!protocolCallFrames->empty()) {
2150 breakReason = protocol::Debugger::Paused::ReasonEnum::Instrumentation;
2152 protocolCallFrames->at(0)->getLocation()->getScriptId();
2154 const auto& script =
m_scripts[scriptId];
2156 breakAuxData = protocol::DictionaryValue::create();
2157 breakAuxData->setString(
"scriptId", script->scriptId());
2158 breakAuxData->setString(
"url", script->sourceURL());
2159 if (!script->sourceMappingURL().isEmpty()) {
2160 breakAuxData->setString(
"sourceMapURL", (script->sourceMappingURL()));
2165 m_frontend.paused(std::move(protocolCallFrames), breakReason,
2166 std::move(breakAuxData),
2167 std::make_unique<Array<String16>>(),
2173 const std::vector<v8::debug::BreakpointId>& hitBreakpoints,
2178 std::vector<BreakReason> hitReasons;
2181 hitReasons.push_back(
2182 std::make_pair(protocol::Debugger::Paused::ReasonEnum::OOM,
nullptr));
2184 hitReasons.push_back(std::make_pair(
2185 protocol::Debugger::Paused::ReasonEnum::Assert,
nullptr));
2189 if (injectedScript) {
2192 ? protocol::Debugger::Paused::ReasonEnum::PromiseRejection
2193 : protocol::Debugger::Paused::ReasonEnum::Exception;
2194 std::unique_ptr<protocol::Runtime::RemoteObject> obj;
2197 std::unique_ptr<protocol::DictionaryValue> breakAuxData;
2199 std::vector<uint8_t> serialized;
2200 obj->AppendSerialized(&serialized);
2201 breakAuxData = protocol::DictionaryValue::cast(
2202 protocol::Value::parseBinary(serialized.data(), serialized.size()));
2203 breakAuxData->setBoolean(
"uncaught", isUncaught);
2205 hitReasons.push_back(
2206 std::make_pair(breakReason, std::move(breakAuxData)));
2212 hitReasons.push_back(
2213 std::make_pair(protocol::Debugger::Paused::ReasonEnum::Step,
nullptr));
2216 auto hitBreakpointIds = std::make_unique<Array<String16>>();
2217 bool hitRegularBreakpoint =
false;
2218 for (
const auto&
id : hitBreakpoints) {
2223 const String16& breakpointId = breakpointIterator->second;
2224 hitBreakpointIds->emplace_back(breakpointId);
2225 BreakpointType
type;
2226 parseBreakpointId(breakpointId, &type);
2227 if (type == BreakpointType::kDebugCommand) {
2228 hitReasons.push_back(std::make_pair(
2229 protocol::Debugger::Paused::ReasonEnum::DebugCommand,
nullptr));
2231 hitRegularBreakpoint =
true;
2242 std::make_pair(protocol::Debugger::Paused::ReasonEnum::Other,
nullptr);
2243 const bool otherBreakReasons =
2244 hitRegularBreakpoint || hitBreakReasonEncodedAsOther(breakReasons);
2245 if (otherBreakReasons && std::find(hitReasons.begin(), hitReasons.end(),
2246 otherHitReason) == hitReasons.end()) {
2247 hitReasons.push_back(
2248 std::make_pair(protocol::Debugger::Paused::ReasonEnum::Other,
nullptr));
2254 DCHECK(hitReasons.size() > 0 || !hitBreakpoints.empty() ||
2256 String16 breakReason = protocol::Debugger::Paused::ReasonEnum::Other;
2257 std::unique_ptr<protocol::DictionaryValue> breakAuxData;
2258 if (hitReasons.size() == 1) {
2259 breakReason = hitReasons[0].first;
2260 breakAuxData = std::move(hitReasons[0].
second);
2261 }
else if (hitReasons.size() > 1) {
2262 breakReason = protocol::Debugger::Paused::ReasonEnum::Ambiguous;
2263 std::unique_ptr<protocol::ListValue> reasons =
2264 protocol::ListValue::create();
2265 for (
size_t i = 0;
i < hitReasons.size(); ++
i) {
2266 std::unique_ptr<protocol::DictionaryValue> reason =
2267 protocol::DictionaryValue::create();
2268 reason->setString(
"reason", hitReasons[
i].first);
2270 reason->setObject(
"auxData", std::move(hitReasons[
i].
second));
2271 reasons->pushValue(std::move(reason));
2273 breakAuxData = protocol::DictionaryValue::create();
2274 breakAuxData->setArray(
"reasons", std::move(reasons));
2277 std::unique_ptr<Array<CallFrame>> protocolCallFrames;
2279 if (!response.IsSuccess())
2280 protocolCallFrames = std::make_unique<Array<CallFrame>>();
2283 m_frontend.paused(std::move(protocolCallFrames), breakReason,
2284 std::move(breakAuxData), std::move(hitBreakpointIds),
2295 std::unique_ptr<protocol::DictionaryValue> data) {
2297 std::vector<BreakReason> currentScheduledReason;
2306 if (!inspector->
sessionById(contextGroupId, sessionId))
return;
2319 String16 breakpointId = generateBreakpointId(
2321 : BreakpointType::kMonitorCommand,
2332 String16 breakpointId = generateBreakpointId(
2334 : BreakpointType::kMonitorCommand,
2336 std::vector<V8DebuggerScript*> scripts;
2355#if V8_ENABLE_WEBASSEMBLY
2357 if (script->wasmBytecode().To(&span)) {
2358 bytecode.reserve(span.size());
2359 bytecode.insert(bytecode.begin(), span.data(), span.data() + span.size());
2363 CachedScript cachedScript{script->scriptId(), script->source(0),
2364 std::move(bytecode)};
2379 protocol::Array<protocol::Debugger::LocationRange>& skipList) {
2380 std::unordered_map<String16, std::vector<std::pair<int, int>>> skipListInit;
2381 for (std::unique_ptr<protocol::Debugger::LocationRange>& range : skipList) {
2382 protocol::Debugger::ScriptPosition*
start = range->getStart();
2383 protocol::Debugger::ScriptPosition*
end = range->getEnd();
2384 String16 scriptId = range->getScriptId();
2388 return Response::ServerError(
"No script with passed id.");
2390 Response res = isValidPosition(
start);
2391 if (res.IsError())
return res;
2393 res = isValidPosition(
end);
2394 if (res.IsError())
return res;
2396 skipListInit[scriptId].emplace_back(
start->getLineNumber(),
2397 start->getColumnNumber());
2398 skipListInit[scriptId].emplace_back(
end->getLineNumber(),
2399 end->getColumnNumber());
2404 for (
const auto& skipListPair : skipListInit) {
2405 Response res = isValidRangeOfPositions(skipListPair.second);
2406 if (res.IsError())
return res;
2410 return Response::Success();
interpreter::Bytecode bytecode
static V8_INLINE Local< T > Cast(Local< S > that)
static constexpr int kMaxLength
V8_INLINE bool IsEmpty() const
constexpr bool contains_any(EnumSet set) const
constexpr bool contains(E element) const
int GetColumnNumber() const
int GetLineNumber() const
virtual int GetScriptId()=0
virtual v8::Local< v8::Object > GetObject()=0
virtual v8::Local< v8::Value > GetFunctionDebugName()=0
virtual debug::Location GetStartLocation()=0
virtual debug::Location GetEndLocation()=0
virtual ScopeType GetType()=0
virtual bool HasLocationInfo()=0
@ ScopeTypeWasmExpressionStack
static std::unique_ptr< StackTraceIterator > Create(Isolate *isolate, int index=0)
size_t total_number_of_lines_
DisassemblyCollectorImpl()=default
std::vector< DisassemblyChunk > chunks_
size_t writing_chunk_index_
DisassemblyChunk NextChunk()
void ReserveLineCount(size_t count) override
static constexpr size_t kLinesPerChunk
size_t total_number_of_lines()
void AddLine(const char *src, size_t length, uint32_t bytecode_offset) override
size_t reading_chunk_index_
size_t frameOrdinal() const
v8::Local< v8::Value > object() const
InjectedScript * injectedScript() const
const v8::TryCatch & tryCatch() const
void ignoreExceptionsAndMuteConsole()
void installCommandLineAPI()
Response wrapObject(v8::Local< v8::Value >, const String16 &groupName, const WrapOptions &wrapOptions, std::unique_ptr< protocol::Runtime::RemoteObject > *result)
Response resolveCallArgument(protocol::Runtime::CallArgument *, v8::Local< v8::Value > *result)
Response wrapEvaluateResult(v8::MaybeLocal< v8::Value > maybeResultValue, const v8::TryCatch &, const String16 &objectGroup, const WrapOptions &wrapOptions, bool throwOnSideEffect, std::unique_ptr< protocol::Runtime::RemoteObject > *result, std::unique_ptr< protocol::Runtime::ExceptionDetails > *)
v8::Local< v8::Context > context() const
internal::V8DebuggerId uniqueId() const
static String16 serialize(uint64_t isolateId, int injectedScriptId, int frameOrdinal)
void append(const String16 &)
String16 substring(size_t pos, size_t len=UINT_MAX) const
static String16 fromInteger(int)
int toInteger(bool *ok=nullptr) const
V8_EXPORT std::string utf8() const
size_t find(const String16 &str, size_t start=0) const
size_t reverseFind(const String16 &str, size_t start=UINT_MAX) const
const uint16_t * characters16() const
std::pair< size_t, size_t > getTrimmedOffsetAndLength() const
static const size_t kNotFound
Response setBlackboxPatterns(std::unique_ptr< protocol::Array< String16 > > patterns, std::optional< bool > skipAnonymous) override
Response setVariableValue(int scopeNumber, const String16 &variableName, std::unique_ptr< protocol::Runtime::CallArgument > newValue, const String16 &callFrame) override
Response setSkipAllPauses(bool skip) override
Response searchInContent(const String16 &scriptId, const String16 &query, std::optional< bool > optionalCaseSensitive, std::optional< bool > optionalIsRegex, std::unique_ptr< protocol::Array< protocol::Debugger::SearchMatch > > *) override
Response disable() override
Response resume(std::optional< bool > terminateOnResume) override
void removeBreakpointFor(v8::Local< v8::Function > function, BreakpointSource source)
V8InspectorSessionImpl * m_session
void cancelPauseOnNextStatement()
Response setBreakpointOnFunctionCall(const String16 &functionObjectId, std::optional< String16 > optionalCondition, String16 *outBreakpointId) override
bool m_skipAnonymousScripts
std::unique_ptr< V8Regex > m_blackboxPattern
void resetBlackboxedStateCache()
void schedulePauseOnNextStatement(const String16 &breakReason, std::unique_ptr< protocol::DictionaryValue > data)
std::map< String16, std::unique_ptr< DisassemblyCollectorImpl > > m_wasmDisassemblies
Response enable(std::optional< double > maxScriptsCacheSize, String16 *outDebuggerId) override
Response setPauseOnExceptions(const String16 &pauseState) override
Response setBreakpointByUrl(int lineNumber, std::optional< String16 > optionalURL, std::optional< String16 > optionalURLRegex, std::optional< String16 > optionalScriptHash, std::optional< int > optionalColumnNumber, std::optional< String16 > optionalCondition, String16 *, std::unique_ptr< protocol::Array< protocol::Debugger::Location > > *locations) override
Response removeBreakpoint(const String16 &breakpointId) override
V8InspectorImpl * m_inspector
Response getScriptSource(const String16 &scriptId, String16 *scriptSource, std::optional< protocol::Binary > *bytecode) override
void ScriptCollected(const V8DebuggerScript *script)
std::vector< BreakReason > m_breakReason
std::unique_ptr< protocol::Runtime::StackTraceId > currentExternalStackTrace()
std::unordered_map< String16, std::vector< std::pair< int, int > > > m_blackboxedPositions
void removeBreakpointImpl(const String16 &breakpointId, const std::vector< V8DebuggerScript * > &scripts)
void setScriptInstrumentationBreakpointIfNeeded(V8DebuggerScript *script)
std::deque< CachedScript > m_cachedScripts
Response setBreakpointsActive(bool active) override
Response continueToLocation(std::unique_ptr< protocol::Debugger::Location >, std::optional< String16 > targetCallFrames) override
Response setInstrumentationBreakpoint(const String16 &instrumentation, String16 *outBreakpointId) override
@ DebugCommandBreakpointSource
void setPauseOnExceptionsImpl(int)
size_t m_maxScriptCacheSize
Response getStackTrace(std::unique_ptr< protocol::Runtime::StackTraceId > inStackTraceId, std::unique_ptr< protocol::Runtime::StackTrace > *outStackTrace) override
Response disassembleWasmModule(const String16 &in_scriptId, std::optional< String16 > *out_streamId, int *out_totalNumberOfLines, std::unique_ptr< protocol::Array< int > > *out_functionBodyOffsets, std::unique_ptr< protocol::Debugger::WasmDisassemblyChunk > *out_chunk) override
std::unique_ptr< protocol::Debugger::Location > setBreakpointImpl(const String16 &breakpointId, const String16 &scriptId, const String16 &condition, int lineNumber, int columnNumber)
size_t m_nextWasmDisassemblyStreamId
Response setScriptSource(const String16 &inScriptId, const String16 &inScriptSource, std::optional< bool > dryRun, std::optional< bool > allowTopFrameEditing, std::unique_ptr< protocol::Array< protocol::Debugger::CallFrame > > *optOutCallFrames, std::optional< bool > *optOutStackChanged, std::unique_ptr< protocol::Runtime::StackTrace > *optOutAsyncStackTrace, std::unique_ptr< protocol::Runtime::StackTraceId > *optOutAsyncStackTraceId, String16 *outStatus, std::unique_ptr< protocol::Runtime::ExceptionDetails > *optOutCompileError) override
Response stepOver(std::unique_ptr< protocol::Array< protocol::Debugger::LocationRange > > inSkipList) override
BreakpointIdToDebuggerBreakpointIdsMap m_breakpointIdToDebuggerBreakpointIds
Response pauseOnAsyncCall(std::unique_ptr< protocol::Runtime::StackTraceId > inParentStackTraceId) override
Response setBreakpoint(std::unique_ptr< protocol::Debugger::Location >, std::optional< String16 > optionalCondition, String16 *, std::unique_ptr< protocol::Debugger::Location > *actualLocation) override
Response setBlackboxExecutionContexts(std::unique_ptr< protocol::Array< String16 > > uniqueIds) override
bool isFunctionBlackboxed(const String16 &scriptId, const v8::debug::Location &start, const v8::debug::Location &end)
Response getPossibleBreakpoints(std::unique_ptr< protocol::Debugger::Location > start, std::unique_ptr< protocol::Debugger::Location > end, std::optional< bool > restrictToFunction, std::unique_ptr< protocol::Array< protocol::Debugger::BreakLocation > > *locations) override
void pushBreakDetails(const String16 &breakReason, std::unique_ptr< protocol::DictionaryValue > breakAuxData)
void didPauseOnInstrumentation(v8::debug::BreakpointId instrumentationId)
Response setReturnValue(std::unique_ptr< protocol::Runtime::CallArgument > newValue) override
Response setBlackboxedRanges(const String16 &scriptId, std::unique_ptr< protocol::Array< protocol::Debugger::ScriptPosition > > positions) override
void setBreakpointFor(v8::Local< v8::Function > function, v8::Local< v8::String > condition, BreakpointSource source)
Response stepInto(std::optional< bool > inBreakOnAsyncCall, std::unique_ptr< protocol::Array< protocol::Debugger::LocationRange > > inSkipList) override
Response restartFrame(const String16 &callFrameId, std::optional< String16 > mode, std::unique_ptr< protocol::Array< protocol::Debugger::CallFrame > > *newCallFrames, std::unique_ptr< protocol::Runtime::StackTrace > *asyncStackTrace, std::unique_ptr< protocol::Runtime::StackTraceId > *asyncStackTraceId) override
V8DebuggerAgentImpl(V8InspectorSessionImpl *, protocol::FrontendChannel *, protocol::DictionaryValue *state)
Response evaluateOnCallFrame(const String16 &callFrameId, const String16 &expression, std::optional< String16 > objectGroup, std::optional< bool > includeCommandLineAPI, std::optional< bool > silent, std::optional< bool > returnByValue, std::optional< bool > generatePreview, std::optional< bool > throwOnSideEffect, std::optional< double > timeout, std::unique_ptr< protocol::Runtime::RemoteObject > *result, std::unique_ptr< protocol::Runtime::ExceptionDetails > *) override
std::unordered_set< String16 > m_blackboxedExecutionContexts
Response processSkipList(protocol::Array< protocol::Debugger::LocationRange > &skipList)
void didPause(int contextId, v8::Local< v8::Value > exception, const std::vector< v8::debug::BreakpointId > &hitBreakpoints, v8::debug::ExceptionType exceptionType, bool isUncaught, v8::debug::BreakReasons breakReasons)
std::pair< String16, std::unique_ptr< protocol::DictionaryValue > > BreakReason
protocol::Debugger::Frontend m_frontend
Response getWasmBytecode(const String16 &scriptId, protocol::Binary *bytecode) override
void breakProgram(const String16 &breakReason, std::unique_ptr< protocol::DictionaryValue > data)
Response setBlackboxPattern(const String16 &pattern)
bool acceptsPause(bool isOOMBreak) const
std::unordered_map< String16, std::vector< std::pair< int, int > > > m_skipList
bool m_instrumentationFinished
std::unique_ptr< protocol::Runtime::StackTrace > currentAsyncStackTrace()
~V8DebuggerAgentImpl() override
Response nextWasmDisassemblyChunk(const String16 &in_streamId, std::unique_ptr< protocol::Debugger::WasmDisassemblyChunk > *out_chunk) override
EnableState m_enableState
void didParseSource(std::unique_ptr< V8DebuggerScript >, bool success)
Response currentCallFrames(std::unique_ptr< protocol::Array< protocol::Debugger::CallFrame > > *)
protocol::DictionaryValue * m_state
Response setAsyncCallStackDepth(int depth) override
Response stepOut() override
size_t m_cachedScriptSize
bool shouldBeSkipped(const String16 &scriptId, int line, int column)
Response pause() override
DebuggerBreakpointIdToBreakpointIdMap m_debuggerBreakpointIdToBreakpointId
virtual const String16 & hash() const =0
virtual const String16 & sourceMappingURL() const =0
const String16 & scriptId() const
virtual int startColumn() const =0
virtual int endColumn() const =0
virtual int length() const =0
virtual int startLine() const =0
virtual String16 buildId() const =0
virtual int endLine() const =0
virtual bool setInstrumentationBreakpoint(int *id) const =0
int executionContextId() const
virtual void resetBlackboxedStateCache()=0
std::shared_ptr< AsyncStackTrace > stackTraceFor(int contextGroupId, const V8StackTraceId &id)
bool isPausedInContextGroup(int contextGroupId) const
int maxAsyncCallChainDepth()
void removeBreakpoint(v8::debug::BreakpointId id)
void setPauseOnNextCall(bool, int targetContextGroupId)
internal::V8DebuggerId debuggerIdFor(int contextGroupId)
void stepOutOfFunction(int targetContextGroupId)
std::vector< std::unique_ptr< V8DebuggerScript > > getCompiledScripts(int contextGroupId, V8DebuggerAgentImpl *agent)
void interruptAndBreak(int targetContextGroupId)
void continueProgram(int targetContextGroupId, bool terminateOnResume=false)
bool isInInstrumentationPause() const
void allAsyncTasksCanceled()
void setBreakpointsActive(bool)
void requestPauseAfterInstrumentation()
std::shared_ptr< AsyncStackTrace > currentAsyncParent()
void setAsyncCallStackDepth(V8DebuggerAgentImpl *, int)
void breakProgram(int targetContextGroupId)
V8StackTraceId currentExternalParent()
void stepIntoStatement(int targetContextGroupId, bool breakOnAsyncCall)
v8::Isolate * isolate() const
void stepOverStatement(int targetContextGroupId)
void setPauseOnExceptionsState(v8::debug::ExceptionBreakState)
bool restartFrame(int targetContextGroupId, int callFrameOrdinal)
Response continueToLocation(int targetContextGroupId, V8DebuggerScript *script, std::unique_ptr< protocol::Debugger::Location >, const String16 &targetCallFramess)
virtual bool canExecuteScripts(int contextGroupId)
protocol::Response setTimeout(double timeout)
InspectedContext * getContext(int groupId, int contextId) const
uint64_t isolateId() override
V8InspectorClient * client()
unsigned nextExceptionId()
int contextGroupId(v8::Local< v8::Context >) const
V8InspectorSessionImpl * sessionById(int contextGroupId, int sessionId)
Response findInjectedScript(int contextId, InjectedScript *&)
void releaseObjectGroup(const String16 &objectGroup)
V8RuntimeAgentImpl * runtimeAgent()
int contextGroupId() const
static std::unique_ptr< V8StackTraceImpl > capture(V8Debugger *, int maxStackSize)
String16 toString() const
std::pair< int64_t, int64_t > pair() const
static Binary fromSpan(v8_crdtp::span< uint8_t > span)
InstructionSelectorT * selector_
ZoneVector< RpoNumber > & result
constexpr Vector< T > VectorOf(T *start, size_t size)
@ kDebuggerStatementBreakLocation
void SetReturnValue(v8::Isolate *v8_isolate, v8::Local< v8::Value > value)
bool SetFunctionBreakpoint(v8::Local< v8::Function > function, v8::Local< v8::String > condition, BreakpointId *id)
@ BreakOnUncaughtException
int GetDebuggingId(v8::Local< v8::Function > function)
void NotifyDebuggerPausedEventSent(v8::Isolate *v8_isolate)
static const char blackboxPattern[]
static const char skipAllPauses[]
static const char pauseOnExceptionsState[]
static const char breakpointsByScriptHash[]
static const char breakpointsActiveWhenEnabled[]
static const char maxScriptCacheSize[]
static const char instrumentationBreakpoints[]
static const char breakpointsByRegex[]
static const char breakpointHintText[]
static const char breakpointHints[]
static const char debuggerEnabled[]
static const char breakpointHintPrefixLength[]
static const char breakpointsByUrl[]
static const char skipAnonymousScripts[]
static const char asyncCallStackDepth[]
static const char breakpointHintPrefixHash[]
static const intptr_t kBreakpointHintMaxSearchOffset
static String16 getScriptLanguage(const V8DebuggerScript &script)
static const size_t kMaxNumBreakpoints
static const char kDebuggerNotEnabled[]
int32_t computeCrc32(const String16 &text)
String16 toProtocolString(v8::Isolate *isolate, v8::Local< v8::String > value)
static const char kDebuggerNotPaused[]
String16 stackTraceIdToString(uintptr_t id)
v8::Local< v8::String > toV8String(v8::Isolate *isolate, const String16 &string)
static const size_t kBreakpointHintMaxLength
std::vector< std::unique_ptr< protocol::Debugger::SearchMatch > > searchInTextByLinesImpl(V8InspectorSession *session, const String16 &text, const String16 &query, const bool caseSensitive, const bool isRegex)
String16 findSourceURL(const String16 &content, bool multiline)
String16 toProtocolStringWithTypeCheck(v8::Isolate *isolate, v8::Local< v8::Value > value)
String16 findSourceMapURL(const String16 &content, bool multiline)
static const char kBacktraceObjectGroup[]
#define DCHECK_NE(v1, v2)
#define DCHECK_GE(v1, v2)
#define DCHECK(condition)
#define DCHECK_GT(v1, v2)
@ BLOCKED_BY_RUNNING_GENERATOR
@ BLOCKED_BY_TOP_LEVEL_ES_MODULE_CHANGE
@ BLOCKED_BY_ACTIVE_FUNCTION
DisassemblyChunk()=default
DisassemblyChunk(DisassemblyChunk &&other) V8_NOEXCEPT=default
void Reserve(size_t size)
std::vector< int > lineOffsets
DisassemblyChunk & operator=(const DisassemblyChunk &other)=delete
DisassemblyChunk & operator=(DisassemblyChunk &&other) V8_NOEXCEPT=default
DisassemblyChunk(const DisassemblyChunk &other)=delete
std::vector< String16 > lines
std::pair< int64_t, int64_t > debugger_id
V8InspectorImpl * m_inspector
std::unique_ptr< V8Regex > regex_
V8InspectorSessionImpl * m_session
protocol::HeapProfiler::Frontend * m_frontend
std::unique_ptr< ValueMirror > value
std::unique_ptr< ValueMirror > key