11cb0ef41Sopenharmony_ci// Copyright 2015 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci#include "src/inspector/v8-debugger-agent-impl.h" 61cb0ef41Sopenharmony_ci 71cb0ef41Sopenharmony_ci#include <algorithm> 81cb0ef41Sopenharmony_ci 91cb0ef41Sopenharmony_ci#include "../../third_party/inspector_protocol/crdtp/json.h" 101cb0ef41Sopenharmony_ci#include "include/v8-context.h" 111cb0ef41Sopenharmony_ci#include "include/v8-function.h" 121cb0ef41Sopenharmony_ci#include "include/v8-inspector.h" 131cb0ef41Sopenharmony_ci#include "include/v8-microtask-queue.h" 141cb0ef41Sopenharmony_ci#include "src/base/safe_conversions.h" 151cb0ef41Sopenharmony_ci#include "src/debug/debug-interface.h" 161cb0ef41Sopenharmony_ci#include "src/inspector/injected-script.h" 171cb0ef41Sopenharmony_ci#include "src/inspector/inspected-context.h" 181cb0ef41Sopenharmony_ci#include "src/inspector/protocol/Debugger.h" 191cb0ef41Sopenharmony_ci#include "src/inspector/protocol/Protocol.h" 201cb0ef41Sopenharmony_ci#include "src/inspector/remote-object-id.h" 211cb0ef41Sopenharmony_ci#include "src/inspector/search-util.h" 221cb0ef41Sopenharmony_ci#include "src/inspector/string-util.h" 231cb0ef41Sopenharmony_ci#include "src/inspector/v8-debugger-script.h" 241cb0ef41Sopenharmony_ci#include "src/inspector/v8-debugger.h" 251cb0ef41Sopenharmony_ci#include "src/inspector/v8-inspector-impl.h" 261cb0ef41Sopenharmony_ci#include "src/inspector/v8-inspector-session-impl.h" 271cb0ef41Sopenharmony_ci#include "src/inspector/v8-regex.h" 281cb0ef41Sopenharmony_ci#include "src/inspector/v8-runtime-agent-impl.h" 291cb0ef41Sopenharmony_ci#include "src/inspector/v8-stack-trace-impl.h" 301cb0ef41Sopenharmony_ci#include "src/inspector/v8-value-utils.h" 311cb0ef41Sopenharmony_ci 321cb0ef41Sopenharmony_cinamespace v8_inspector { 331cb0ef41Sopenharmony_ci 341cb0ef41Sopenharmony_ciusing protocol::Array; 351cb0ef41Sopenharmony_ciusing protocol::Maybe; 361cb0ef41Sopenharmony_ciusing protocol::Debugger::BreakpointId; 371cb0ef41Sopenharmony_ciusing protocol::Debugger::CallFrame; 381cb0ef41Sopenharmony_ciusing protocol::Debugger::Scope; 391cb0ef41Sopenharmony_ciusing protocol::Runtime::ExceptionDetails; 401cb0ef41Sopenharmony_ciusing protocol::Runtime::RemoteObject; 411cb0ef41Sopenharmony_ciusing protocol::Runtime::ScriptId; 421cb0ef41Sopenharmony_ci 431cb0ef41Sopenharmony_cinamespace InstrumentationEnum = 441cb0ef41Sopenharmony_ci protocol::Debugger::SetInstrumentationBreakpoint::InstrumentationEnum; 451cb0ef41Sopenharmony_ci 461cb0ef41Sopenharmony_cinamespace DebuggerAgentState { 471cb0ef41Sopenharmony_cistatic const char pauseOnExceptionsState[] = "pauseOnExceptionsState"; 481cb0ef41Sopenharmony_cistatic const char asyncCallStackDepth[] = "asyncCallStackDepth"; 491cb0ef41Sopenharmony_cistatic const char blackboxPattern[] = "blackboxPattern"; 501cb0ef41Sopenharmony_cistatic const char debuggerEnabled[] = "debuggerEnabled"; 511cb0ef41Sopenharmony_cistatic const char skipAllPauses[] = "skipAllPauses"; 521cb0ef41Sopenharmony_ci 531cb0ef41Sopenharmony_cistatic const char breakpointsByRegex[] = "breakpointsByRegex"; 541cb0ef41Sopenharmony_cistatic const char breakpointsByUrl[] = "breakpointsByUrl"; 551cb0ef41Sopenharmony_cistatic const char breakpointsByScriptHash[] = "breakpointsByScriptHash"; 561cb0ef41Sopenharmony_cistatic const char breakpointHints[] = "breakpointHints"; 571cb0ef41Sopenharmony_cistatic const char instrumentationBreakpoints[] = "instrumentationBreakpoints"; 581cb0ef41Sopenharmony_ci 591cb0ef41Sopenharmony_ci} // namespace DebuggerAgentState 601cb0ef41Sopenharmony_ci 611cb0ef41Sopenharmony_cistatic const char kBacktraceObjectGroup[] = "backtrace"; 621cb0ef41Sopenharmony_cistatic const char kDebuggerNotEnabled[] = "Debugger agent is not enabled"; 631cb0ef41Sopenharmony_cistatic const char kDebuggerNotPaused[] = 641cb0ef41Sopenharmony_ci "Can only perform operation while paused."; 651cb0ef41Sopenharmony_ci 661cb0ef41Sopenharmony_cistatic const size_t kBreakpointHintMaxLength = 128; 671cb0ef41Sopenharmony_cistatic const intptr_t kBreakpointHintMaxSearchOffset = 80 * 10; 681cb0ef41Sopenharmony_ci// Limit the number of breakpoints returned, as we otherwise may exceed 691cb0ef41Sopenharmony_ci// the maximum length of a message in mojo (see https://crbug.com/1105172). 701cb0ef41Sopenharmony_cistatic const size_t kMaxNumBreakpoints = 1000; 711cb0ef41Sopenharmony_ci 721cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY 731cb0ef41Sopenharmony_ci// TODO(1099680): getScriptSource and getWasmBytecode return Wasm wire bytes 741cb0ef41Sopenharmony_ci// as protocol::Binary, which is encoded as JSON string in the communication 751cb0ef41Sopenharmony_ci// to the DevTools front-end and hence leads to either crashing the renderer 761cb0ef41Sopenharmony_ci// that is being debugged or the renderer that's running the front-end if we 771cb0ef41Sopenharmony_ci// allow arbitrarily big Wasm byte sequences here. Ideally we would find a 781cb0ef41Sopenharmony_ci// different way to transfer the wire bytes (middle- to long-term), but as a 791cb0ef41Sopenharmony_ci// short-term solution, we should at least not crash. 801cb0ef41Sopenharmony_cistatic constexpr size_t kWasmBytecodeMaxLength = 811cb0ef41Sopenharmony_ci (v8::String::kMaxLength / 4) * 3; 821cb0ef41Sopenharmony_cistatic constexpr const char kWasmBytecodeExceedsTransferLimit[] = 831cb0ef41Sopenharmony_ci "WebAssembly bytecode exceeds the transfer limit"; 841cb0ef41Sopenharmony_ci#endif // V8_ENABLE_WEBASSEMBLY 851cb0ef41Sopenharmony_ci 861cb0ef41Sopenharmony_cinamespace { 871cb0ef41Sopenharmony_ci 881cb0ef41Sopenharmony_cienum class BreakpointType { 891cb0ef41Sopenharmony_ci kByUrl = 1, 901cb0ef41Sopenharmony_ci kByUrlRegex, 911cb0ef41Sopenharmony_ci kByScriptHash, 921cb0ef41Sopenharmony_ci kByScriptId, 931cb0ef41Sopenharmony_ci kDebugCommand, 941cb0ef41Sopenharmony_ci kMonitorCommand, 951cb0ef41Sopenharmony_ci kBreakpointAtEntry, 961cb0ef41Sopenharmony_ci kInstrumentationBreakpoint 971cb0ef41Sopenharmony_ci}; 981cb0ef41Sopenharmony_ci 991cb0ef41Sopenharmony_ciString16 generateBreakpointId(BreakpointType type, 1001cb0ef41Sopenharmony_ci const String16& scriptSelector, int lineNumber, 1011cb0ef41Sopenharmony_ci int columnNumber) { 1021cb0ef41Sopenharmony_ci String16Builder builder; 1031cb0ef41Sopenharmony_ci builder.appendNumber(static_cast<int>(type)); 1041cb0ef41Sopenharmony_ci builder.append(':'); 1051cb0ef41Sopenharmony_ci builder.appendNumber(lineNumber); 1061cb0ef41Sopenharmony_ci builder.append(':'); 1071cb0ef41Sopenharmony_ci builder.appendNumber(columnNumber); 1081cb0ef41Sopenharmony_ci builder.append(':'); 1091cb0ef41Sopenharmony_ci builder.append(scriptSelector); 1101cb0ef41Sopenharmony_ci return builder.toString(); 1111cb0ef41Sopenharmony_ci} 1121cb0ef41Sopenharmony_ci 1131cb0ef41Sopenharmony_ciString16 generateBreakpointId(BreakpointType type, 1141cb0ef41Sopenharmony_ci v8::Local<v8::Function> function) { 1151cb0ef41Sopenharmony_ci String16Builder builder; 1161cb0ef41Sopenharmony_ci builder.appendNumber(static_cast<int>(type)); 1171cb0ef41Sopenharmony_ci builder.append(':'); 1181cb0ef41Sopenharmony_ci builder.appendNumber(v8::debug::GetDebuggingId(function)); 1191cb0ef41Sopenharmony_ci return builder.toString(); 1201cb0ef41Sopenharmony_ci} 1211cb0ef41Sopenharmony_ci 1221cb0ef41Sopenharmony_ciString16 generateInstrumentationBreakpointId(const String16& instrumentation) { 1231cb0ef41Sopenharmony_ci String16Builder builder; 1241cb0ef41Sopenharmony_ci builder.appendNumber( 1251cb0ef41Sopenharmony_ci static_cast<int>(BreakpointType::kInstrumentationBreakpoint)); 1261cb0ef41Sopenharmony_ci builder.append(':'); 1271cb0ef41Sopenharmony_ci builder.append(instrumentation); 1281cb0ef41Sopenharmony_ci return builder.toString(); 1291cb0ef41Sopenharmony_ci} 1301cb0ef41Sopenharmony_ci 1311cb0ef41Sopenharmony_cibool parseBreakpointId(const String16& breakpointId, BreakpointType* type, 1321cb0ef41Sopenharmony_ci String16* scriptSelector = nullptr, 1331cb0ef41Sopenharmony_ci int* lineNumber = nullptr, int* columnNumber = nullptr) { 1341cb0ef41Sopenharmony_ci size_t typeLineSeparator = breakpointId.find(':'); 1351cb0ef41Sopenharmony_ci if (typeLineSeparator == String16::kNotFound) return false; 1361cb0ef41Sopenharmony_ci 1371cb0ef41Sopenharmony_ci int rawType = breakpointId.substring(0, typeLineSeparator).toInteger(); 1381cb0ef41Sopenharmony_ci if (rawType < static_cast<int>(BreakpointType::kByUrl) || 1391cb0ef41Sopenharmony_ci rawType > static_cast<int>(BreakpointType::kInstrumentationBreakpoint)) { 1401cb0ef41Sopenharmony_ci return false; 1411cb0ef41Sopenharmony_ci } 1421cb0ef41Sopenharmony_ci if (type) *type = static_cast<BreakpointType>(rawType); 1431cb0ef41Sopenharmony_ci if (rawType == static_cast<int>(BreakpointType::kDebugCommand) || 1441cb0ef41Sopenharmony_ci rawType == static_cast<int>(BreakpointType::kMonitorCommand) || 1451cb0ef41Sopenharmony_ci rawType == static_cast<int>(BreakpointType::kBreakpointAtEntry) || 1461cb0ef41Sopenharmony_ci rawType == static_cast<int>(BreakpointType::kInstrumentationBreakpoint)) { 1471cb0ef41Sopenharmony_ci // The script and source position are not encoded in this case. 1481cb0ef41Sopenharmony_ci return true; 1491cb0ef41Sopenharmony_ci } 1501cb0ef41Sopenharmony_ci 1511cb0ef41Sopenharmony_ci size_t lineColumnSeparator = breakpointId.find(':', typeLineSeparator + 1); 1521cb0ef41Sopenharmony_ci if (lineColumnSeparator == String16::kNotFound) return false; 1531cb0ef41Sopenharmony_ci size_t columnSelectorSeparator = 1541cb0ef41Sopenharmony_ci breakpointId.find(':', lineColumnSeparator + 1); 1551cb0ef41Sopenharmony_ci if (columnSelectorSeparator == String16::kNotFound) return false; 1561cb0ef41Sopenharmony_ci if (scriptSelector) { 1571cb0ef41Sopenharmony_ci *scriptSelector = breakpointId.substring(columnSelectorSeparator + 1); 1581cb0ef41Sopenharmony_ci } 1591cb0ef41Sopenharmony_ci if (lineNumber) { 1601cb0ef41Sopenharmony_ci *lineNumber = breakpointId 1611cb0ef41Sopenharmony_ci .substring(typeLineSeparator + 1, 1621cb0ef41Sopenharmony_ci lineColumnSeparator - typeLineSeparator - 1) 1631cb0ef41Sopenharmony_ci .toInteger(); 1641cb0ef41Sopenharmony_ci } 1651cb0ef41Sopenharmony_ci if (columnNumber) { 1661cb0ef41Sopenharmony_ci *columnNumber = 1671cb0ef41Sopenharmony_ci breakpointId 1681cb0ef41Sopenharmony_ci .substring(lineColumnSeparator + 1, 1691cb0ef41Sopenharmony_ci columnSelectorSeparator - lineColumnSeparator - 1) 1701cb0ef41Sopenharmony_ci .toInteger(); 1711cb0ef41Sopenharmony_ci } 1721cb0ef41Sopenharmony_ci return true; 1731cb0ef41Sopenharmony_ci} 1741cb0ef41Sopenharmony_ci 1751cb0ef41Sopenharmony_cibool positionComparator(const std::pair<int, int>& a, 1761cb0ef41Sopenharmony_ci const std::pair<int, int>& b) { 1771cb0ef41Sopenharmony_ci if (a.first != b.first) return a.first < b.first; 1781cb0ef41Sopenharmony_ci return a.second < b.second; 1791cb0ef41Sopenharmony_ci} 1801cb0ef41Sopenharmony_ci 1811cb0ef41Sopenharmony_ciString16 breakpointHint(const V8DebuggerScript& script, int lineNumber, 1821cb0ef41Sopenharmony_ci int columnNumber) { 1831cb0ef41Sopenharmony_ci int offset = script.offset(lineNumber, columnNumber); 1841cb0ef41Sopenharmony_ci if (offset == V8DebuggerScript::kNoOffset) return String16(); 1851cb0ef41Sopenharmony_ci String16 hint = 1861cb0ef41Sopenharmony_ci script.source(offset, kBreakpointHintMaxLength).stripWhiteSpace(); 1871cb0ef41Sopenharmony_ci for (size_t i = 0; i < hint.length(); ++i) { 1881cb0ef41Sopenharmony_ci if (hint[i] == '\r' || hint[i] == '\n' || hint[i] == ';') { 1891cb0ef41Sopenharmony_ci return hint.substring(0, i); 1901cb0ef41Sopenharmony_ci } 1911cb0ef41Sopenharmony_ci } 1921cb0ef41Sopenharmony_ci return hint; 1931cb0ef41Sopenharmony_ci} 1941cb0ef41Sopenharmony_ci 1951cb0ef41Sopenharmony_civoid adjustBreakpointLocation(const V8DebuggerScript& script, 1961cb0ef41Sopenharmony_ci const String16& hint, int* lineNumber, 1971cb0ef41Sopenharmony_ci int* columnNumber) { 1981cb0ef41Sopenharmony_ci if (*lineNumber < script.startLine() || *lineNumber > script.endLine()) 1991cb0ef41Sopenharmony_ci return; 2001cb0ef41Sopenharmony_ci if (*lineNumber == script.startLine() && 2011cb0ef41Sopenharmony_ci *columnNumber < script.startColumn()) { 2021cb0ef41Sopenharmony_ci return; 2031cb0ef41Sopenharmony_ci } 2041cb0ef41Sopenharmony_ci if (*lineNumber == script.endLine() && script.endColumn() < *columnNumber) { 2051cb0ef41Sopenharmony_ci return; 2061cb0ef41Sopenharmony_ci } 2071cb0ef41Sopenharmony_ci 2081cb0ef41Sopenharmony_ci if (hint.isEmpty()) return; 2091cb0ef41Sopenharmony_ci intptr_t sourceOffset = script.offset(*lineNumber, *columnNumber); 2101cb0ef41Sopenharmony_ci if (sourceOffset == V8DebuggerScript::kNoOffset) return; 2111cb0ef41Sopenharmony_ci 2121cb0ef41Sopenharmony_ci intptr_t searchRegionOffset = std::max( 2131cb0ef41Sopenharmony_ci sourceOffset - kBreakpointHintMaxSearchOffset, static_cast<intptr_t>(0)); 2141cb0ef41Sopenharmony_ci size_t offset = sourceOffset - searchRegionOffset; 2151cb0ef41Sopenharmony_ci String16 searchArea = script.source(searchRegionOffset, 2161cb0ef41Sopenharmony_ci offset + kBreakpointHintMaxSearchOffset); 2171cb0ef41Sopenharmony_ci 2181cb0ef41Sopenharmony_ci size_t nextMatch = searchArea.find(hint, offset); 2191cb0ef41Sopenharmony_ci size_t prevMatch = searchArea.reverseFind(hint, offset); 2201cb0ef41Sopenharmony_ci if (nextMatch == String16::kNotFound && prevMatch == String16::kNotFound) { 2211cb0ef41Sopenharmony_ci return; 2221cb0ef41Sopenharmony_ci } 2231cb0ef41Sopenharmony_ci size_t bestMatch; 2241cb0ef41Sopenharmony_ci if (nextMatch == String16::kNotFound) { 2251cb0ef41Sopenharmony_ci bestMatch = prevMatch; 2261cb0ef41Sopenharmony_ci } else if (prevMatch == String16::kNotFound) { 2271cb0ef41Sopenharmony_ci bestMatch = nextMatch; 2281cb0ef41Sopenharmony_ci } else { 2291cb0ef41Sopenharmony_ci bestMatch = nextMatch - offset < offset - prevMatch ? nextMatch : prevMatch; 2301cb0ef41Sopenharmony_ci } 2311cb0ef41Sopenharmony_ci bestMatch += searchRegionOffset; 2321cb0ef41Sopenharmony_ci v8::debug::Location hintPosition = 2331cb0ef41Sopenharmony_ci script.location(static_cast<int>(bestMatch)); 2341cb0ef41Sopenharmony_ci if (hintPosition.IsEmpty()) return; 2351cb0ef41Sopenharmony_ci *lineNumber = hintPosition.GetLineNumber(); 2361cb0ef41Sopenharmony_ci *columnNumber = hintPosition.GetColumnNumber(); 2371cb0ef41Sopenharmony_ci} 2381cb0ef41Sopenharmony_ci 2391cb0ef41Sopenharmony_ciString16 breakLocationType(v8::debug::BreakLocationType type) { 2401cb0ef41Sopenharmony_ci switch (type) { 2411cb0ef41Sopenharmony_ci case v8::debug::kCallBreakLocation: 2421cb0ef41Sopenharmony_ci return protocol::Debugger::BreakLocation::TypeEnum::Call; 2431cb0ef41Sopenharmony_ci case v8::debug::kReturnBreakLocation: 2441cb0ef41Sopenharmony_ci return protocol::Debugger::BreakLocation::TypeEnum::Return; 2451cb0ef41Sopenharmony_ci case v8::debug::kDebuggerStatementBreakLocation: 2461cb0ef41Sopenharmony_ci return protocol::Debugger::BreakLocation::TypeEnum::DebuggerStatement; 2471cb0ef41Sopenharmony_ci case v8::debug::kCommonBreakLocation: 2481cb0ef41Sopenharmony_ci return String16(); 2491cb0ef41Sopenharmony_ci } 2501cb0ef41Sopenharmony_ci return String16(); 2511cb0ef41Sopenharmony_ci} 2521cb0ef41Sopenharmony_ci 2531cb0ef41Sopenharmony_ciString16 scopeType(v8::debug::ScopeIterator::ScopeType type) { 2541cb0ef41Sopenharmony_ci switch (type) { 2551cb0ef41Sopenharmony_ci case v8::debug::ScopeIterator::ScopeTypeGlobal: 2561cb0ef41Sopenharmony_ci return Scope::TypeEnum::Global; 2571cb0ef41Sopenharmony_ci case v8::debug::ScopeIterator::ScopeTypeLocal: 2581cb0ef41Sopenharmony_ci return Scope::TypeEnum::Local; 2591cb0ef41Sopenharmony_ci case v8::debug::ScopeIterator::ScopeTypeWith: 2601cb0ef41Sopenharmony_ci return Scope::TypeEnum::With; 2611cb0ef41Sopenharmony_ci case v8::debug::ScopeIterator::ScopeTypeClosure: 2621cb0ef41Sopenharmony_ci return Scope::TypeEnum::Closure; 2631cb0ef41Sopenharmony_ci case v8::debug::ScopeIterator::ScopeTypeCatch: 2641cb0ef41Sopenharmony_ci return Scope::TypeEnum::Catch; 2651cb0ef41Sopenharmony_ci case v8::debug::ScopeIterator::ScopeTypeBlock: 2661cb0ef41Sopenharmony_ci return Scope::TypeEnum::Block; 2671cb0ef41Sopenharmony_ci case v8::debug::ScopeIterator::ScopeTypeScript: 2681cb0ef41Sopenharmony_ci return Scope::TypeEnum::Script; 2691cb0ef41Sopenharmony_ci case v8::debug::ScopeIterator::ScopeTypeEval: 2701cb0ef41Sopenharmony_ci return Scope::TypeEnum::Eval; 2711cb0ef41Sopenharmony_ci case v8::debug::ScopeIterator::ScopeTypeModule: 2721cb0ef41Sopenharmony_ci return Scope::TypeEnum::Module; 2731cb0ef41Sopenharmony_ci case v8::debug::ScopeIterator::ScopeTypeWasmExpressionStack: 2741cb0ef41Sopenharmony_ci return Scope::TypeEnum::WasmExpressionStack; 2751cb0ef41Sopenharmony_ci } 2761cb0ef41Sopenharmony_ci UNREACHABLE(); 2771cb0ef41Sopenharmony_ci} 2781cb0ef41Sopenharmony_ci 2791cb0ef41Sopenharmony_ciResponse buildScopes(v8::Isolate* isolate, v8::debug::ScopeIterator* iterator, 2801cb0ef41Sopenharmony_ci InjectedScript* injectedScript, 2811cb0ef41Sopenharmony_ci std::unique_ptr<Array<Scope>>* scopes) { 2821cb0ef41Sopenharmony_ci *scopes = std::make_unique<Array<Scope>>(); 2831cb0ef41Sopenharmony_ci if (!injectedScript) return Response::Success(); 2841cb0ef41Sopenharmony_ci if (iterator->Done()) return Response::Success(); 2851cb0ef41Sopenharmony_ci 2861cb0ef41Sopenharmony_ci String16 scriptId = String16::fromInteger(iterator->GetScriptId()); 2871cb0ef41Sopenharmony_ci 2881cb0ef41Sopenharmony_ci for (; !iterator->Done(); iterator->Advance()) { 2891cb0ef41Sopenharmony_ci std::unique_ptr<RemoteObject> object; 2901cb0ef41Sopenharmony_ci Response result = 2911cb0ef41Sopenharmony_ci injectedScript->wrapObject(iterator->GetObject(), kBacktraceObjectGroup, 2921cb0ef41Sopenharmony_ci WrapMode::kNoPreview, &object); 2931cb0ef41Sopenharmony_ci if (!result.IsSuccess()) return result; 2941cb0ef41Sopenharmony_ci 2951cb0ef41Sopenharmony_ci auto scope = Scope::create() 2961cb0ef41Sopenharmony_ci .setType(scopeType(iterator->GetType())) 2971cb0ef41Sopenharmony_ci .setObject(std::move(object)) 2981cb0ef41Sopenharmony_ci .build(); 2991cb0ef41Sopenharmony_ci 3001cb0ef41Sopenharmony_ci String16 name = toProtocolStringWithTypeCheck( 3011cb0ef41Sopenharmony_ci isolate, iterator->GetFunctionDebugName()); 3021cb0ef41Sopenharmony_ci if (!name.isEmpty()) scope->setName(name); 3031cb0ef41Sopenharmony_ci 3041cb0ef41Sopenharmony_ci if (iterator->HasLocationInfo()) { 3051cb0ef41Sopenharmony_ci v8::debug::Location start = iterator->GetStartLocation(); 3061cb0ef41Sopenharmony_ci scope->setStartLocation(protocol::Debugger::Location::create() 3071cb0ef41Sopenharmony_ci .setScriptId(scriptId) 3081cb0ef41Sopenharmony_ci .setLineNumber(start.GetLineNumber()) 3091cb0ef41Sopenharmony_ci .setColumnNumber(start.GetColumnNumber()) 3101cb0ef41Sopenharmony_ci .build()); 3111cb0ef41Sopenharmony_ci 3121cb0ef41Sopenharmony_ci v8::debug::Location end = iterator->GetEndLocation(); 3131cb0ef41Sopenharmony_ci scope->setEndLocation(protocol::Debugger::Location::create() 3141cb0ef41Sopenharmony_ci .setScriptId(scriptId) 3151cb0ef41Sopenharmony_ci .setLineNumber(end.GetLineNumber()) 3161cb0ef41Sopenharmony_ci .setColumnNumber(end.GetColumnNumber()) 3171cb0ef41Sopenharmony_ci .build()); 3181cb0ef41Sopenharmony_ci } 3191cb0ef41Sopenharmony_ci (*scopes)->emplace_back(std::move(scope)); 3201cb0ef41Sopenharmony_ci } 3211cb0ef41Sopenharmony_ci return Response::Success(); 3221cb0ef41Sopenharmony_ci} 3231cb0ef41Sopenharmony_ci 3241cb0ef41Sopenharmony_ciprotocol::DictionaryValue* getOrCreateObject(protocol::DictionaryValue* object, 3251cb0ef41Sopenharmony_ci const String16& key) { 3261cb0ef41Sopenharmony_ci protocol::DictionaryValue* value = object->getObject(key); 3271cb0ef41Sopenharmony_ci if (value) return value; 3281cb0ef41Sopenharmony_ci std::unique_ptr<protocol::DictionaryValue> newDictionary = 3291cb0ef41Sopenharmony_ci protocol::DictionaryValue::create(); 3301cb0ef41Sopenharmony_ci value = newDictionary.get(); 3311cb0ef41Sopenharmony_ci object->setObject(key, std::move(newDictionary)); 3321cb0ef41Sopenharmony_ci return value; 3331cb0ef41Sopenharmony_ci} 3341cb0ef41Sopenharmony_ci 3351cb0ef41Sopenharmony_ciResponse isValidPosition(protocol::Debugger::ScriptPosition* position) { 3361cb0ef41Sopenharmony_ci if (position->getLineNumber() < 0) 3371cb0ef41Sopenharmony_ci return Response::ServerError("Position missing 'line' or 'line' < 0."); 3381cb0ef41Sopenharmony_ci if (position->getColumnNumber() < 0) 3391cb0ef41Sopenharmony_ci return Response::ServerError("Position missing 'column' or 'column' < 0."); 3401cb0ef41Sopenharmony_ci return Response::Success(); 3411cb0ef41Sopenharmony_ci} 3421cb0ef41Sopenharmony_ci 3431cb0ef41Sopenharmony_ciResponse isValidRangeOfPositions(std::vector<std::pair<int, int>>& positions) { 3441cb0ef41Sopenharmony_ci for (size_t i = 1; i < positions.size(); ++i) { 3451cb0ef41Sopenharmony_ci if (positions[i - 1].first < positions[i].first) continue; 3461cb0ef41Sopenharmony_ci if (positions[i - 1].first == positions[i].first && 3471cb0ef41Sopenharmony_ci positions[i - 1].second < positions[i].second) 3481cb0ef41Sopenharmony_ci continue; 3491cb0ef41Sopenharmony_ci return Response::ServerError( 3501cb0ef41Sopenharmony_ci "Input positions array is not sorted or contains duplicate values."); 3511cb0ef41Sopenharmony_ci } 3521cb0ef41Sopenharmony_ci return Response::Success(); 3531cb0ef41Sopenharmony_ci} 3541cb0ef41Sopenharmony_ci 3551cb0ef41Sopenharmony_cibool hitBreakReasonEncodedAsOther(v8::debug::BreakReasons breakReasons) { 3561cb0ef41Sopenharmony_ci // The listed break reasons are not explicitly encoded in CDP when 3571cb0ef41Sopenharmony_ci // reporting the break. They are summarized as 'other'. 3581cb0ef41Sopenharmony_ci v8::debug::BreakReasons otherBreakReasons( 3591cb0ef41Sopenharmony_ci {v8::debug::BreakReason::kStep, 3601cb0ef41Sopenharmony_ci v8::debug::BreakReason::kDebuggerStatement, 3611cb0ef41Sopenharmony_ci v8::debug::BreakReason::kScheduled, v8::debug::BreakReason::kAsyncStep, 3621cb0ef41Sopenharmony_ci v8::debug::BreakReason::kAlreadyPaused}); 3631cb0ef41Sopenharmony_ci return breakReasons.contains_any(otherBreakReasons); 3641cb0ef41Sopenharmony_ci} 3651cb0ef41Sopenharmony_ci} // namespace 3661cb0ef41Sopenharmony_ci 3671cb0ef41Sopenharmony_ciV8DebuggerAgentImpl::V8DebuggerAgentImpl( 3681cb0ef41Sopenharmony_ci V8InspectorSessionImpl* session, protocol::FrontendChannel* frontendChannel, 3691cb0ef41Sopenharmony_ci protocol::DictionaryValue* state) 3701cb0ef41Sopenharmony_ci : m_inspector(session->inspector()), 3711cb0ef41Sopenharmony_ci m_debugger(m_inspector->debugger()), 3721cb0ef41Sopenharmony_ci m_session(session), 3731cb0ef41Sopenharmony_ci m_enabled(false), 3741cb0ef41Sopenharmony_ci m_state(state), 3751cb0ef41Sopenharmony_ci m_frontend(frontendChannel), 3761cb0ef41Sopenharmony_ci m_isolate(m_inspector->isolate()) {} 3771cb0ef41Sopenharmony_ci 3781cb0ef41Sopenharmony_ciV8DebuggerAgentImpl::~V8DebuggerAgentImpl() = default; 3791cb0ef41Sopenharmony_ci 3801cb0ef41Sopenharmony_civoid V8DebuggerAgentImpl::enableImpl() { 3811cb0ef41Sopenharmony_ci m_enabled = true; 3821cb0ef41Sopenharmony_ci m_state->setBoolean(DebuggerAgentState::debuggerEnabled, true); 3831cb0ef41Sopenharmony_ci m_debugger->enable(); 3841cb0ef41Sopenharmony_ci 3851cb0ef41Sopenharmony_ci std::vector<std::unique_ptr<V8DebuggerScript>> compiledScripts = 3861cb0ef41Sopenharmony_ci m_debugger->getCompiledScripts(m_session->contextGroupId(), this); 3871cb0ef41Sopenharmony_ci for (auto& script : compiledScripts) { 3881cb0ef41Sopenharmony_ci didParseSource(std::move(script), true); 3891cb0ef41Sopenharmony_ci } 3901cb0ef41Sopenharmony_ci 3911cb0ef41Sopenharmony_ci m_breakpointsActive = true; 3921cb0ef41Sopenharmony_ci m_debugger->setBreakpointsActive(true); 3931cb0ef41Sopenharmony_ci 3941cb0ef41Sopenharmony_ci if (isPaused()) { 3951cb0ef41Sopenharmony_ci didPause(0, v8::Local<v8::Value>(), std::vector<v8::debug::BreakpointId>(), 3961cb0ef41Sopenharmony_ci v8::debug::kException, false, 3971cb0ef41Sopenharmony_ci v8::debug::BreakReasons({v8::debug::BreakReason::kAlreadyPaused})); 3981cb0ef41Sopenharmony_ci } 3991cb0ef41Sopenharmony_ci} 4001cb0ef41Sopenharmony_ci 4011cb0ef41Sopenharmony_ciResponse V8DebuggerAgentImpl::enable(Maybe<double> maxScriptsCacheSize, 4021cb0ef41Sopenharmony_ci String16* outDebuggerId) { 4031cb0ef41Sopenharmony_ci m_maxScriptCacheSize = v8::base::saturated_cast<size_t>( 4041cb0ef41Sopenharmony_ci maxScriptsCacheSize.fromMaybe(std::numeric_limits<double>::max())); 4051cb0ef41Sopenharmony_ci *outDebuggerId = 4061cb0ef41Sopenharmony_ci m_debugger->debuggerIdFor(m_session->contextGroupId()).toString(); 4071cb0ef41Sopenharmony_ci if (enabled()) return Response::Success(); 4081cb0ef41Sopenharmony_ci 4091cb0ef41Sopenharmony_ci if (!m_inspector->client()->canExecuteScripts(m_session->contextGroupId())) 4101cb0ef41Sopenharmony_ci return Response::ServerError("Script execution is prohibited"); 4111cb0ef41Sopenharmony_ci 4121cb0ef41Sopenharmony_ci enableImpl(); 4131cb0ef41Sopenharmony_ci return Response::Success(); 4141cb0ef41Sopenharmony_ci} 4151cb0ef41Sopenharmony_ci 4161cb0ef41Sopenharmony_ciResponse V8DebuggerAgentImpl::disable() { 4171cb0ef41Sopenharmony_ci if (!enabled()) return Response::Success(); 4181cb0ef41Sopenharmony_ci 4191cb0ef41Sopenharmony_ci m_state->remove(DebuggerAgentState::breakpointsByRegex); 4201cb0ef41Sopenharmony_ci m_state->remove(DebuggerAgentState::breakpointsByUrl); 4211cb0ef41Sopenharmony_ci m_state->remove(DebuggerAgentState::breakpointsByScriptHash); 4221cb0ef41Sopenharmony_ci m_state->remove(DebuggerAgentState::breakpointHints); 4231cb0ef41Sopenharmony_ci m_state->remove(DebuggerAgentState::instrumentationBreakpoints); 4241cb0ef41Sopenharmony_ci 4251cb0ef41Sopenharmony_ci m_state->setInteger(DebuggerAgentState::pauseOnExceptionsState, 4261cb0ef41Sopenharmony_ci v8::debug::NoBreakOnException); 4271cb0ef41Sopenharmony_ci m_state->setInteger(DebuggerAgentState::asyncCallStackDepth, 0); 4281cb0ef41Sopenharmony_ci 4291cb0ef41Sopenharmony_ci if (m_breakpointsActive) { 4301cb0ef41Sopenharmony_ci m_debugger->setBreakpointsActive(false); 4311cb0ef41Sopenharmony_ci m_breakpointsActive = false; 4321cb0ef41Sopenharmony_ci } 4331cb0ef41Sopenharmony_ci m_blackboxedPositions.clear(); 4341cb0ef41Sopenharmony_ci m_blackboxPattern.reset(); 4351cb0ef41Sopenharmony_ci resetBlackboxedStateCache(); 4361cb0ef41Sopenharmony_ci m_skipList.clear(); 4371cb0ef41Sopenharmony_ci m_scripts.clear(); 4381cb0ef41Sopenharmony_ci m_cachedScripts.clear(); 4391cb0ef41Sopenharmony_ci m_cachedScriptSize = 0; 4401cb0ef41Sopenharmony_ci for (const auto& it : m_debuggerBreakpointIdToBreakpointId) { 4411cb0ef41Sopenharmony_ci v8::debug::RemoveBreakpoint(m_isolate, it.first); 4421cb0ef41Sopenharmony_ci } 4431cb0ef41Sopenharmony_ci m_breakpointIdToDebuggerBreakpointIds.clear(); 4441cb0ef41Sopenharmony_ci m_debuggerBreakpointIdToBreakpointId.clear(); 4451cb0ef41Sopenharmony_ci m_debugger->setAsyncCallStackDepth(this, 0); 4461cb0ef41Sopenharmony_ci clearBreakDetails(); 4471cb0ef41Sopenharmony_ci m_skipAllPauses = false; 4481cb0ef41Sopenharmony_ci m_state->setBoolean(DebuggerAgentState::skipAllPauses, false); 4491cb0ef41Sopenharmony_ci m_state->remove(DebuggerAgentState::blackboxPattern); 4501cb0ef41Sopenharmony_ci m_enabled = false; 4511cb0ef41Sopenharmony_ci m_state->setBoolean(DebuggerAgentState::debuggerEnabled, false); 4521cb0ef41Sopenharmony_ci m_debugger->disable(); 4531cb0ef41Sopenharmony_ci return Response::Success(); 4541cb0ef41Sopenharmony_ci} 4551cb0ef41Sopenharmony_ci 4561cb0ef41Sopenharmony_civoid V8DebuggerAgentImpl::restore() { 4571cb0ef41Sopenharmony_ci DCHECK(!m_enabled); 4581cb0ef41Sopenharmony_ci if (!m_state->booleanProperty(DebuggerAgentState::debuggerEnabled, false)) 4591cb0ef41Sopenharmony_ci return; 4601cb0ef41Sopenharmony_ci if (!m_inspector->client()->canExecuteScripts(m_session->contextGroupId())) 4611cb0ef41Sopenharmony_ci return; 4621cb0ef41Sopenharmony_ci 4631cb0ef41Sopenharmony_ci enableImpl(); 4641cb0ef41Sopenharmony_ci 4651cb0ef41Sopenharmony_ci int pauseState = v8::debug::NoBreakOnException; 4661cb0ef41Sopenharmony_ci m_state->getInteger(DebuggerAgentState::pauseOnExceptionsState, &pauseState); 4671cb0ef41Sopenharmony_ci setPauseOnExceptionsImpl(pauseState); 4681cb0ef41Sopenharmony_ci 4691cb0ef41Sopenharmony_ci m_skipAllPauses = 4701cb0ef41Sopenharmony_ci m_state->booleanProperty(DebuggerAgentState::skipAllPauses, false); 4711cb0ef41Sopenharmony_ci 4721cb0ef41Sopenharmony_ci int asyncCallStackDepth = 0; 4731cb0ef41Sopenharmony_ci m_state->getInteger(DebuggerAgentState::asyncCallStackDepth, 4741cb0ef41Sopenharmony_ci &asyncCallStackDepth); 4751cb0ef41Sopenharmony_ci m_debugger->setAsyncCallStackDepth(this, asyncCallStackDepth); 4761cb0ef41Sopenharmony_ci 4771cb0ef41Sopenharmony_ci String16 blackboxPattern; 4781cb0ef41Sopenharmony_ci if (m_state->getString(DebuggerAgentState::blackboxPattern, 4791cb0ef41Sopenharmony_ci &blackboxPattern)) { 4801cb0ef41Sopenharmony_ci setBlackboxPattern(blackboxPattern); 4811cb0ef41Sopenharmony_ci } 4821cb0ef41Sopenharmony_ci} 4831cb0ef41Sopenharmony_ci 4841cb0ef41Sopenharmony_ciResponse V8DebuggerAgentImpl::setBreakpointsActive(bool active) { 4851cb0ef41Sopenharmony_ci if (!enabled()) return Response::ServerError(kDebuggerNotEnabled); 4861cb0ef41Sopenharmony_ci if (m_breakpointsActive == active) return Response::Success(); 4871cb0ef41Sopenharmony_ci m_breakpointsActive = active; 4881cb0ef41Sopenharmony_ci m_debugger->setBreakpointsActive(active); 4891cb0ef41Sopenharmony_ci if (!active && !m_breakReason.empty()) { 4901cb0ef41Sopenharmony_ci clearBreakDetails(); 4911cb0ef41Sopenharmony_ci m_debugger->setPauseOnNextCall(false, m_session->contextGroupId()); 4921cb0ef41Sopenharmony_ci } 4931cb0ef41Sopenharmony_ci return Response::Success(); 4941cb0ef41Sopenharmony_ci} 4951cb0ef41Sopenharmony_ci 4961cb0ef41Sopenharmony_ciResponse V8DebuggerAgentImpl::setSkipAllPauses(bool skip) { 4971cb0ef41Sopenharmony_ci m_state->setBoolean(DebuggerAgentState::skipAllPauses, skip); 4981cb0ef41Sopenharmony_ci m_skipAllPauses = skip; 4991cb0ef41Sopenharmony_ci return Response::Success(); 5001cb0ef41Sopenharmony_ci} 5011cb0ef41Sopenharmony_ci 5021cb0ef41Sopenharmony_cistatic bool matches(V8InspectorImpl* inspector, const V8DebuggerScript& script, 5031cb0ef41Sopenharmony_ci BreakpointType type, const String16& selector) { 5041cb0ef41Sopenharmony_ci switch (type) { 5051cb0ef41Sopenharmony_ci case BreakpointType::kByUrl: 5061cb0ef41Sopenharmony_ci return script.sourceURL() == selector; 5071cb0ef41Sopenharmony_ci case BreakpointType::kByScriptHash: 5081cb0ef41Sopenharmony_ci return script.hash() == selector; 5091cb0ef41Sopenharmony_ci case BreakpointType::kByUrlRegex: { 5101cb0ef41Sopenharmony_ci V8Regex regex(inspector, selector, true); 5111cb0ef41Sopenharmony_ci return regex.match(script.sourceURL()) != -1; 5121cb0ef41Sopenharmony_ci } 5131cb0ef41Sopenharmony_ci case BreakpointType::kByScriptId: { 5141cb0ef41Sopenharmony_ci return script.scriptId() == selector; 5151cb0ef41Sopenharmony_ci } 5161cb0ef41Sopenharmony_ci default: 5171cb0ef41Sopenharmony_ci return false; 5181cb0ef41Sopenharmony_ci } 5191cb0ef41Sopenharmony_ci} 5201cb0ef41Sopenharmony_ci 5211cb0ef41Sopenharmony_ciResponse V8DebuggerAgentImpl::setBreakpointByUrl( 5221cb0ef41Sopenharmony_ci int lineNumber, Maybe<String16> optionalURL, 5231cb0ef41Sopenharmony_ci Maybe<String16> optionalURLRegex, Maybe<String16> optionalScriptHash, 5241cb0ef41Sopenharmony_ci Maybe<int> optionalColumnNumber, Maybe<String16> optionalCondition, 5251cb0ef41Sopenharmony_ci String16* outBreakpointId, 5261cb0ef41Sopenharmony_ci std::unique_ptr<protocol::Array<protocol::Debugger::Location>>* locations) { 5271cb0ef41Sopenharmony_ci if (!enabled()) return Response::ServerError(kDebuggerNotEnabled); 5281cb0ef41Sopenharmony_ci 5291cb0ef41Sopenharmony_ci *locations = std::make_unique<Array<protocol::Debugger::Location>>(); 5301cb0ef41Sopenharmony_ci 5311cb0ef41Sopenharmony_ci int specified = (optionalURL.isJust() ? 1 : 0) + 5321cb0ef41Sopenharmony_ci (optionalURLRegex.isJust() ? 1 : 0) + 5331cb0ef41Sopenharmony_ci (optionalScriptHash.isJust() ? 1 : 0); 5341cb0ef41Sopenharmony_ci if (specified != 1) { 5351cb0ef41Sopenharmony_ci return Response::ServerError( 5361cb0ef41Sopenharmony_ci "Either url or urlRegex or scriptHash must be specified."); 5371cb0ef41Sopenharmony_ci } 5381cb0ef41Sopenharmony_ci int columnNumber = 0; 5391cb0ef41Sopenharmony_ci if (optionalColumnNumber.isJust()) { 5401cb0ef41Sopenharmony_ci columnNumber = optionalColumnNumber.fromJust(); 5411cb0ef41Sopenharmony_ci if (columnNumber < 0) 5421cb0ef41Sopenharmony_ci return Response::ServerError("Incorrect column number"); 5431cb0ef41Sopenharmony_ci } 5441cb0ef41Sopenharmony_ci 5451cb0ef41Sopenharmony_ci BreakpointType type = BreakpointType::kByUrl; 5461cb0ef41Sopenharmony_ci String16 selector; 5471cb0ef41Sopenharmony_ci if (optionalURLRegex.isJust()) { 5481cb0ef41Sopenharmony_ci selector = optionalURLRegex.fromJust(); 5491cb0ef41Sopenharmony_ci type = BreakpointType::kByUrlRegex; 5501cb0ef41Sopenharmony_ci } else if (optionalURL.isJust()) { 5511cb0ef41Sopenharmony_ci selector = optionalURL.fromJust(); 5521cb0ef41Sopenharmony_ci type = BreakpointType::kByUrl; 5531cb0ef41Sopenharmony_ci } else if (optionalScriptHash.isJust()) { 5541cb0ef41Sopenharmony_ci selector = optionalScriptHash.fromJust(); 5551cb0ef41Sopenharmony_ci type = BreakpointType::kByScriptHash; 5561cb0ef41Sopenharmony_ci } 5571cb0ef41Sopenharmony_ci 5581cb0ef41Sopenharmony_ci String16 condition = optionalCondition.fromMaybe(String16()); 5591cb0ef41Sopenharmony_ci String16 breakpointId = 5601cb0ef41Sopenharmony_ci generateBreakpointId(type, selector, lineNumber, columnNumber); 5611cb0ef41Sopenharmony_ci protocol::DictionaryValue* breakpoints; 5621cb0ef41Sopenharmony_ci switch (type) { 5631cb0ef41Sopenharmony_ci case BreakpointType::kByUrlRegex: 5641cb0ef41Sopenharmony_ci breakpoints = 5651cb0ef41Sopenharmony_ci getOrCreateObject(m_state, DebuggerAgentState::breakpointsByRegex); 5661cb0ef41Sopenharmony_ci break; 5671cb0ef41Sopenharmony_ci case BreakpointType::kByUrl: 5681cb0ef41Sopenharmony_ci breakpoints = getOrCreateObject( 5691cb0ef41Sopenharmony_ci getOrCreateObject(m_state, DebuggerAgentState::breakpointsByUrl), 5701cb0ef41Sopenharmony_ci selector); 5711cb0ef41Sopenharmony_ci break; 5721cb0ef41Sopenharmony_ci case BreakpointType::kByScriptHash: 5731cb0ef41Sopenharmony_ci breakpoints = getOrCreateObject( 5741cb0ef41Sopenharmony_ci getOrCreateObject(m_state, 5751cb0ef41Sopenharmony_ci DebuggerAgentState::breakpointsByScriptHash), 5761cb0ef41Sopenharmony_ci selector); 5771cb0ef41Sopenharmony_ci break; 5781cb0ef41Sopenharmony_ci default: 5791cb0ef41Sopenharmony_ci UNREACHABLE(); 5801cb0ef41Sopenharmony_ci } 5811cb0ef41Sopenharmony_ci if (breakpoints->get(breakpointId)) { 5821cb0ef41Sopenharmony_ci return Response::ServerError( 5831cb0ef41Sopenharmony_ci "Breakpoint at specified location already exists."); 5841cb0ef41Sopenharmony_ci } 5851cb0ef41Sopenharmony_ci 5861cb0ef41Sopenharmony_ci String16 hint; 5871cb0ef41Sopenharmony_ci for (const auto& script : m_scripts) { 5881cb0ef41Sopenharmony_ci if (!matches(m_inspector, *script.second, type, selector)) continue; 5891cb0ef41Sopenharmony_ci if (!hint.isEmpty()) { 5901cb0ef41Sopenharmony_ci adjustBreakpointLocation(*script.second, hint, &lineNumber, 5911cb0ef41Sopenharmony_ci &columnNumber); 5921cb0ef41Sopenharmony_ci } 5931cb0ef41Sopenharmony_ci std::unique_ptr<protocol::Debugger::Location> location = setBreakpointImpl( 5941cb0ef41Sopenharmony_ci breakpointId, script.first, condition, lineNumber, columnNumber); 5951cb0ef41Sopenharmony_ci if (location && type != BreakpointType::kByUrlRegex) { 5961cb0ef41Sopenharmony_ci hint = breakpointHint(*script.second, location->getLineNumber(), 5971cb0ef41Sopenharmony_ci location->getColumnNumber(columnNumber)); 5981cb0ef41Sopenharmony_ci } 5991cb0ef41Sopenharmony_ci if (location) (*locations)->emplace_back(std::move(location)); 6001cb0ef41Sopenharmony_ci } 6011cb0ef41Sopenharmony_ci breakpoints->setString(breakpointId, condition); 6021cb0ef41Sopenharmony_ci if (!hint.isEmpty()) { 6031cb0ef41Sopenharmony_ci protocol::DictionaryValue* breakpointHints = 6041cb0ef41Sopenharmony_ci getOrCreateObject(m_state, DebuggerAgentState::breakpointHints); 6051cb0ef41Sopenharmony_ci breakpointHints->setString(breakpointId, hint); 6061cb0ef41Sopenharmony_ci } 6071cb0ef41Sopenharmony_ci *outBreakpointId = breakpointId; 6081cb0ef41Sopenharmony_ci return Response::Success(); 6091cb0ef41Sopenharmony_ci} 6101cb0ef41Sopenharmony_ci 6111cb0ef41Sopenharmony_ciResponse V8DebuggerAgentImpl::setBreakpoint( 6121cb0ef41Sopenharmony_ci std::unique_ptr<protocol::Debugger::Location> location, 6131cb0ef41Sopenharmony_ci Maybe<String16> optionalCondition, String16* outBreakpointId, 6141cb0ef41Sopenharmony_ci std::unique_ptr<protocol::Debugger::Location>* actualLocation) { 6151cb0ef41Sopenharmony_ci String16 breakpointId = generateBreakpointId( 6161cb0ef41Sopenharmony_ci BreakpointType::kByScriptId, location->getScriptId(), 6171cb0ef41Sopenharmony_ci location->getLineNumber(), location->getColumnNumber(0)); 6181cb0ef41Sopenharmony_ci if (!enabled()) return Response::ServerError(kDebuggerNotEnabled); 6191cb0ef41Sopenharmony_ci 6201cb0ef41Sopenharmony_ci if (m_breakpointIdToDebuggerBreakpointIds.find(breakpointId) != 6211cb0ef41Sopenharmony_ci m_breakpointIdToDebuggerBreakpointIds.end()) { 6221cb0ef41Sopenharmony_ci return Response::ServerError( 6231cb0ef41Sopenharmony_ci "Breakpoint at specified location already exists."); 6241cb0ef41Sopenharmony_ci } 6251cb0ef41Sopenharmony_ci *actualLocation = setBreakpointImpl(breakpointId, location->getScriptId(), 6261cb0ef41Sopenharmony_ci optionalCondition.fromMaybe(String16()), 6271cb0ef41Sopenharmony_ci location->getLineNumber(), 6281cb0ef41Sopenharmony_ci location->getColumnNumber(0)); 6291cb0ef41Sopenharmony_ci if (!*actualLocation) 6301cb0ef41Sopenharmony_ci return Response::ServerError("Could not resolve breakpoint"); 6311cb0ef41Sopenharmony_ci *outBreakpointId = breakpointId; 6321cb0ef41Sopenharmony_ci return Response::Success(); 6331cb0ef41Sopenharmony_ci} 6341cb0ef41Sopenharmony_ci 6351cb0ef41Sopenharmony_ciResponse V8DebuggerAgentImpl::setBreakpointOnFunctionCall( 6361cb0ef41Sopenharmony_ci const String16& functionObjectId, Maybe<String16> optionalCondition, 6371cb0ef41Sopenharmony_ci String16* outBreakpointId) { 6381cb0ef41Sopenharmony_ci if (!enabled()) return Response::ServerError(kDebuggerNotEnabled); 6391cb0ef41Sopenharmony_ci 6401cb0ef41Sopenharmony_ci InjectedScript::ObjectScope scope(m_session, functionObjectId); 6411cb0ef41Sopenharmony_ci Response response = scope.initialize(); 6421cb0ef41Sopenharmony_ci if (!response.IsSuccess()) return response; 6431cb0ef41Sopenharmony_ci if (!scope.object()->IsFunction()) { 6441cb0ef41Sopenharmony_ci return Response::ServerError("Could not find function with given id"); 6451cb0ef41Sopenharmony_ci } 6461cb0ef41Sopenharmony_ci v8::Local<v8::Function> function = 6471cb0ef41Sopenharmony_ci v8::Local<v8::Function>::Cast(scope.object()); 6481cb0ef41Sopenharmony_ci String16 breakpointId = 6491cb0ef41Sopenharmony_ci generateBreakpointId(BreakpointType::kBreakpointAtEntry, function); 6501cb0ef41Sopenharmony_ci if (m_breakpointIdToDebuggerBreakpointIds.find(breakpointId) != 6511cb0ef41Sopenharmony_ci m_breakpointIdToDebuggerBreakpointIds.end()) { 6521cb0ef41Sopenharmony_ci return Response::ServerError( 6531cb0ef41Sopenharmony_ci "Breakpoint at specified location already exists."); 6541cb0ef41Sopenharmony_ci } 6551cb0ef41Sopenharmony_ci v8::Local<v8::String> condition = 6561cb0ef41Sopenharmony_ci toV8String(m_isolate, optionalCondition.fromMaybe(String16())); 6571cb0ef41Sopenharmony_ci setBreakpointImpl(breakpointId, function, condition); 6581cb0ef41Sopenharmony_ci *outBreakpointId = breakpointId; 6591cb0ef41Sopenharmony_ci return Response::Success(); 6601cb0ef41Sopenharmony_ci} 6611cb0ef41Sopenharmony_ci 6621cb0ef41Sopenharmony_ciResponse V8DebuggerAgentImpl::setInstrumentationBreakpoint( 6631cb0ef41Sopenharmony_ci const String16& instrumentation, String16* outBreakpointId) { 6641cb0ef41Sopenharmony_ci if (!enabled()) return Response::ServerError(kDebuggerNotEnabled); 6651cb0ef41Sopenharmony_ci String16 breakpointId = generateInstrumentationBreakpointId(instrumentation); 6661cb0ef41Sopenharmony_ci protocol::DictionaryValue* breakpoints = getOrCreateObject( 6671cb0ef41Sopenharmony_ci m_state, DebuggerAgentState::instrumentationBreakpoints); 6681cb0ef41Sopenharmony_ci if (breakpoints->get(breakpointId)) { 6691cb0ef41Sopenharmony_ci return Response::ServerError( 6701cb0ef41Sopenharmony_ci "Instrumentation breakpoint is already enabled."); 6711cb0ef41Sopenharmony_ci } 6721cb0ef41Sopenharmony_ci breakpoints->setBoolean(breakpointId, true); 6731cb0ef41Sopenharmony_ci *outBreakpointId = breakpointId; 6741cb0ef41Sopenharmony_ci return Response::Success(); 6751cb0ef41Sopenharmony_ci} 6761cb0ef41Sopenharmony_ci 6771cb0ef41Sopenharmony_ciResponse V8DebuggerAgentImpl::removeBreakpoint(const String16& breakpointId) { 6781cb0ef41Sopenharmony_ci if (!enabled()) return Response::ServerError(kDebuggerNotEnabled); 6791cb0ef41Sopenharmony_ci BreakpointType type; 6801cb0ef41Sopenharmony_ci String16 selector; 6811cb0ef41Sopenharmony_ci if (!parseBreakpointId(breakpointId, &type, &selector)) { 6821cb0ef41Sopenharmony_ci return Response::Success(); 6831cb0ef41Sopenharmony_ci } 6841cb0ef41Sopenharmony_ci protocol::DictionaryValue* breakpoints = nullptr; 6851cb0ef41Sopenharmony_ci switch (type) { 6861cb0ef41Sopenharmony_ci case BreakpointType::kByUrl: { 6871cb0ef41Sopenharmony_ci protocol::DictionaryValue* breakpointsByUrl = 6881cb0ef41Sopenharmony_ci m_state->getObject(DebuggerAgentState::breakpointsByUrl); 6891cb0ef41Sopenharmony_ci if (breakpointsByUrl) { 6901cb0ef41Sopenharmony_ci breakpoints = breakpointsByUrl->getObject(selector); 6911cb0ef41Sopenharmony_ci } 6921cb0ef41Sopenharmony_ci } break; 6931cb0ef41Sopenharmony_ci case BreakpointType::kByScriptHash: { 6941cb0ef41Sopenharmony_ci protocol::DictionaryValue* breakpointsByScriptHash = 6951cb0ef41Sopenharmony_ci m_state->getObject(DebuggerAgentState::breakpointsByScriptHash); 6961cb0ef41Sopenharmony_ci if (breakpointsByScriptHash) { 6971cb0ef41Sopenharmony_ci breakpoints = breakpointsByScriptHash->getObject(selector); 6981cb0ef41Sopenharmony_ci } 6991cb0ef41Sopenharmony_ci } break; 7001cb0ef41Sopenharmony_ci case BreakpointType::kByUrlRegex: 7011cb0ef41Sopenharmony_ci breakpoints = m_state->getObject(DebuggerAgentState::breakpointsByRegex); 7021cb0ef41Sopenharmony_ci break; 7031cb0ef41Sopenharmony_ci case BreakpointType::kInstrumentationBreakpoint: 7041cb0ef41Sopenharmony_ci breakpoints = 7051cb0ef41Sopenharmony_ci m_state->getObject(DebuggerAgentState::instrumentationBreakpoints); 7061cb0ef41Sopenharmony_ci break; 7071cb0ef41Sopenharmony_ci default: 7081cb0ef41Sopenharmony_ci break; 7091cb0ef41Sopenharmony_ci } 7101cb0ef41Sopenharmony_ci if (breakpoints) breakpoints->remove(breakpointId); 7111cb0ef41Sopenharmony_ci protocol::DictionaryValue* breakpointHints = 7121cb0ef41Sopenharmony_ci m_state->getObject(DebuggerAgentState::breakpointHints); 7131cb0ef41Sopenharmony_ci if (breakpointHints) breakpointHints->remove(breakpointId); 7141cb0ef41Sopenharmony_ci 7151cb0ef41Sopenharmony_ci // Get a list of scripts to remove breakpoints. 7161cb0ef41Sopenharmony_ci // TODO(duongn): we can do better here if from breakpoint id we can tell it is 7171cb0ef41Sopenharmony_ci // not Wasm breakpoint. 7181cb0ef41Sopenharmony_ci std::vector<V8DebuggerScript*> scripts; 7191cb0ef41Sopenharmony_ci for (const auto& scriptIter : m_scripts) { 7201cb0ef41Sopenharmony_ci const bool scriptSelectorMatch = 7211cb0ef41Sopenharmony_ci matches(m_inspector, *scriptIter.second, type, selector); 7221cb0ef41Sopenharmony_ci const bool isInstrumentation = 7231cb0ef41Sopenharmony_ci type == BreakpointType::kInstrumentationBreakpoint; 7241cb0ef41Sopenharmony_ci if (!scriptSelectorMatch && !isInstrumentation) continue; 7251cb0ef41Sopenharmony_ci V8DebuggerScript* script = scriptIter.second.get(); 7261cb0ef41Sopenharmony_ci if (script->getLanguage() == V8DebuggerScript::Language::WebAssembly) { 7271cb0ef41Sopenharmony_ci scripts.push_back(script); 7281cb0ef41Sopenharmony_ci } 7291cb0ef41Sopenharmony_ci } 7301cb0ef41Sopenharmony_ci removeBreakpointImpl(breakpointId, scripts); 7311cb0ef41Sopenharmony_ci 7321cb0ef41Sopenharmony_ci return Response::Success(); 7331cb0ef41Sopenharmony_ci} 7341cb0ef41Sopenharmony_ci 7351cb0ef41Sopenharmony_civoid V8DebuggerAgentImpl::removeBreakpointImpl( 7361cb0ef41Sopenharmony_ci const String16& breakpointId, 7371cb0ef41Sopenharmony_ci const std::vector<V8DebuggerScript*>& scripts) { 7381cb0ef41Sopenharmony_ci DCHECK(enabled()); 7391cb0ef41Sopenharmony_ci BreakpointIdToDebuggerBreakpointIdsMap::iterator 7401cb0ef41Sopenharmony_ci debuggerBreakpointIdsIterator = 7411cb0ef41Sopenharmony_ci m_breakpointIdToDebuggerBreakpointIds.find(breakpointId); 7421cb0ef41Sopenharmony_ci if (debuggerBreakpointIdsIterator == 7431cb0ef41Sopenharmony_ci m_breakpointIdToDebuggerBreakpointIds.end()) { 7441cb0ef41Sopenharmony_ci return; 7451cb0ef41Sopenharmony_ci } 7461cb0ef41Sopenharmony_ci for (const auto& id : debuggerBreakpointIdsIterator->second) { 7471cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY 7481cb0ef41Sopenharmony_ci for (auto& script : scripts) { 7491cb0ef41Sopenharmony_ci script->removeWasmBreakpoint(id); 7501cb0ef41Sopenharmony_ci } 7511cb0ef41Sopenharmony_ci#endif // V8_ENABLE_WEBASSEMBLY 7521cb0ef41Sopenharmony_ci v8::debug::RemoveBreakpoint(m_isolate, id); 7531cb0ef41Sopenharmony_ci m_debuggerBreakpointIdToBreakpointId.erase(id); 7541cb0ef41Sopenharmony_ci } 7551cb0ef41Sopenharmony_ci m_breakpointIdToDebuggerBreakpointIds.erase(breakpointId); 7561cb0ef41Sopenharmony_ci} 7571cb0ef41Sopenharmony_ci 7581cb0ef41Sopenharmony_ciResponse V8DebuggerAgentImpl::getPossibleBreakpoints( 7591cb0ef41Sopenharmony_ci std::unique_ptr<protocol::Debugger::Location> start, 7601cb0ef41Sopenharmony_ci Maybe<protocol::Debugger::Location> end, Maybe<bool> restrictToFunction, 7611cb0ef41Sopenharmony_ci std::unique_ptr<protocol::Array<protocol::Debugger::BreakLocation>>* 7621cb0ef41Sopenharmony_ci locations) { 7631cb0ef41Sopenharmony_ci String16 scriptId = start->getScriptId(); 7641cb0ef41Sopenharmony_ci 7651cb0ef41Sopenharmony_ci if (start->getLineNumber() < 0 || start->getColumnNumber(0) < 0) 7661cb0ef41Sopenharmony_ci return Response::ServerError( 7671cb0ef41Sopenharmony_ci "start.lineNumber and start.columnNumber should be >= 0"); 7681cb0ef41Sopenharmony_ci 7691cb0ef41Sopenharmony_ci v8::debug::Location v8Start(start->getLineNumber(), 7701cb0ef41Sopenharmony_ci start->getColumnNumber(0)); 7711cb0ef41Sopenharmony_ci v8::debug::Location v8End; 7721cb0ef41Sopenharmony_ci if (end.isJust()) { 7731cb0ef41Sopenharmony_ci if (end.fromJust()->getScriptId() != scriptId) 7741cb0ef41Sopenharmony_ci return Response::ServerError( 7751cb0ef41Sopenharmony_ci "Locations should contain the same scriptId"); 7761cb0ef41Sopenharmony_ci int line = end.fromJust()->getLineNumber(); 7771cb0ef41Sopenharmony_ci int column = end.fromJust()->getColumnNumber(0); 7781cb0ef41Sopenharmony_ci if (line < 0 || column < 0) 7791cb0ef41Sopenharmony_ci return Response::ServerError( 7801cb0ef41Sopenharmony_ci "end.lineNumber and end.columnNumber should be >= 0"); 7811cb0ef41Sopenharmony_ci v8End = v8::debug::Location(line, column); 7821cb0ef41Sopenharmony_ci } 7831cb0ef41Sopenharmony_ci auto it = m_scripts.find(scriptId); 7841cb0ef41Sopenharmony_ci if (it == m_scripts.end()) return Response::ServerError("Script not found"); 7851cb0ef41Sopenharmony_ci std::vector<v8::debug::BreakLocation> v8Locations; 7861cb0ef41Sopenharmony_ci { 7871cb0ef41Sopenharmony_ci v8::HandleScope handleScope(m_isolate); 7881cb0ef41Sopenharmony_ci int contextId = it->second->executionContextId(); 7891cb0ef41Sopenharmony_ci InspectedContext* inspected = m_inspector->getContext(contextId); 7901cb0ef41Sopenharmony_ci if (!inspected) { 7911cb0ef41Sopenharmony_ci return Response::ServerError("Cannot retrive script context"); 7921cb0ef41Sopenharmony_ci } 7931cb0ef41Sopenharmony_ci v8::Context::Scope contextScope(inspected->context()); 7941cb0ef41Sopenharmony_ci v8::MicrotasksScope microtasks(m_isolate, 7951cb0ef41Sopenharmony_ci v8::MicrotasksScope::kDoNotRunMicrotasks); 7961cb0ef41Sopenharmony_ci v8::TryCatch tryCatch(m_isolate); 7971cb0ef41Sopenharmony_ci it->second->getPossibleBreakpoints( 7981cb0ef41Sopenharmony_ci v8Start, v8End, restrictToFunction.fromMaybe(false), &v8Locations); 7991cb0ef41Sopenharmony_ci } 8001cb0ef41Sopenharmony_ci 8011cb0ef41Sopenharmony_ci *locations = 8021cb0ef41Sopenharmony_ci std::make_unique<protocol::Array<protocol::Debugger::BreakLocation>>(); 8031cb0ef41Sopenharmony_ci 8041cb0ef41Sopenharmony_ci // TODO(1106269): Return an error instead of capping the number of 8051cb0ef41Sopenharmony_ci // breakpoints. 8061cb0ef41Sopenharmony_ci const size_t numBreakpointsToSend = 8071cb0ef41Sopenharmony_ci std::min(v8Locations.size(), kMaxNumBreakpoints); 8081cb0ef41Sopenharmony_ci for (size_t i = 0; i < numBreakpointsToSend; ++i) { 8091cb0ef41Sopenharmony_ci std::unique_ptr<protocol::Debugger::BreakLocation> breakLocation = 8101cb0ef41Sopenharmony_ci protocol::Debugger::BreakLocation::create() 8111cb0ef41Sopenharmony_ci .setScriptId(scriptId) 8121cb0ef41Sopenharmony_ci .setLineNumber(v8Locations[i].GetLineNumber()) 8131cb0ef41Sopenharmony_ci .setColumnNumber(v8Locations[i].GetColumnNumber()) 8141cb0ef41Sopenharmony_ci .build(); 8151cb0ef41Sopenharmony_ci if (v8Locations[i].type() != v8::debug::kCommonBreakLocation) { 8161cb0ef41Sopenharmony_ci breakLocation->setType(breakLocationType(v8Locations[i].type())); 8171cb0ef41Sopenharmony_ci } 8181cb0ef41Sopenharmony_ci (*locations)->emplace_back(std::move(breakLocation)); 8191cb0ef41Sopenharmony_ci } 8201cb0ef41Sopenharmony_ci return Response::Success(); 8211cb0ef41Sopenharmony_ci} 8221cb0ef41Sopenharmony_ci 8231cb0ef41Sopenharmony_ciResponse V8DebuggerAgentImpl::continueToLocation( 8241cb0ef41Sopenharmony_ci std::unique_ptr<protocol::Debugger::Location> location, 8251cb0ef41Sopenharmony_ci Maybe<String16> targetCallFrames) { 8261cb0ef41Sopenharmony_ci if (!enabled()) return Response::ServerError(kDebuggerNotEnabled); 8271cb0ef41Sopenharmony_ci if (!isPaused()) return Response::ServerError(kDebuggerNotPaused); 8281cb0ef41Sopenharmony_ci ScriptsMap::iterator it = m_scripts.find(location->getScriptId()); 8291cb0ef41Sopenharmony_ci if (it == m_scripts.end()) { 8301cb0ef41Sopenharmony_ci return Response::ServerError("Cannot continue to specified location"); 8311cb0ef41Sopenharmony_ci } 8321cb0ef41Sopenharmony_ci V8DebuggerScript* script = it->second.get(); 8331cb0ef41Sopenharmony_ci int contextId = script->executionContextId(); 8341cb0ef41Sopenharmony_ci InspectedContext* inspected = m_inspector->getContext(contextId); 8351cb0ef41Sopenharmony_ci if (!inspected) 8361cb0ef41Sopenharmony_ci return Response::ServerError("Cannot continue to specified location"); 8371cb0ef41Sopenharmony_ci v8::HandleScope handleScope(m_isolate); 8381cb0ef41Sopenharmony_ci v8::Context::Scope contextScope(inspected->context()); 8391cb0ef41Sopenharmony_ci return m_debugger->continueToLocation( 8401cb0ef41Sopenharmony_ci m_session->contextGroupId(), script, std::move(location), 8411cb0ef41Sopenharmony_ci targetCallFrames.fromMaybe( 8421cb0ef41Sopenharmony_ci protocol::Debugger::ContinueToLocation::TargetCallFramesEnum::Any)); 8431cb0ef41Sopenharmony_ci} 8441cb0ef41Sopenharmony_ci 8451cb0ef41Sopenharmony_ciResponse V8DebuggerAgentImpl::getStackTrace( 8461cb0ef41Sopenharmony_ci std::unique_ptr<protocol::Runtime::StackTraceId> inStackTraceId, 8471cb0ef41Sopenharmony_ci std::unique_ptr<protocol::Runtime::StackTrace>* outStackTrace) { 8481cb0ef41Sopenharmony_ci bool isOk = false; 8491cb0ef41Sopenharmony_ci int64_t id = inStackTraceId->getId().toInteger64(&isOk); 8501cb0ef41Sopenharmony_ci if (!isOk) return Response::ServerError("Invalid stack trace id"); 8511cb0ef41Sopenharmony_ci 8521cb0ef41Sopenharmony_ci internal::V8DebuggerId debuggerId; 8531cb0ef41Sopenharmony_ci if (inStackTraceId->hasDebuggerId()) { 8541cb0ef41Sopenharmony_ci debuggerId = 8551cb0ef41Sopenharmony_ci internal::V8DebuggerId(inStackTraceId->getDebuggerId(String16())); 8561cb0ef41Sopenharmony_ci } else { 8571cb0ef41Sopenharmony_ci debuggerId = m_debugger->debuggerIdFor(m_session->contextGroupId()); 8581cb0ef41Sopenharmony_ci } 8591cb0ef41Sopenharmony_ci if (!debuggerId.isValid()) 8601cb0ef41Sopenharmony_ci return Response::ServerError("Invalid stack trace id"); 8611cb0ef41Sopenharmony_ci 8621cb0ef41Sopenharmony_ci V8StackTraceId v8StackTraceId(id, debuggerId.pair()); 8631cb0ef41Sopenharmony_ci if (v8StackTraceId.IsInvalid()) 8641cb0ef41Sopenharmony_ci return Response::ServerError("Invalid stack trace id"); 8651cb0ef41Sopenharmony_ci auto stack = 8661cb0ef41Sopenharmony_ci m_debugger->stackTraceFor(m_session->contextGroupId(), v8StackTraceId); 8671cb0ef41Sopenharmony_ci if (!stack) { 8681cb0ef41Sopenharmony_ci return Response::ServerError("Stack trace with given id is not found"); 8691cb0ef41Sopenharmony_ci } 8701cb0ef41Sopenharmony_ci *outStackTrace = stack->buildInspectorObject( 8711cb0ef41Sopenharmony_ci m_debugger, m_debugger->maxAsyncCallChainDepth()); 8721cb0ef41Sopenharmony_ci return Response::Success(); 8731cb0ef41Sopenharmony_ci} 8741cb0ef41Sopenharmony_ci 8751cb0ef41Sopenharmony_cibool V8DebuggerAgentImpl::isFunctionBlackboxed(const String16& scriptId, 8761cb0ef41Sopenharmony_ci const v8::debug::Location& start, 8771cb0ef41Sopenharmony_ci const v8::debug::Location& end) { 8781cb0ef41Sopenharmony_ci ScriptsMap::iterator it = m_scripts.find(scriptId); 8791cb0ef41Sopenharmony_ci if (it == m_scripts.end()) { 8801cb0ef41Sopenharmony_ci // Unknown scripts are blackboxed. 8811cb0ef41Sopenharmony_ci return true; 8821cb0ef41Sopenharmony_ci } 8831cb0ef41Sopenharmony_ci if (m_blackboxPattern) { 8841cb0ef41Sopenharmony_ci const String16& scriptSourceURL = it->second->sourceURL(); 8851cb0ef41Sopenharmony_ci if (!scriptSourceURL.isEmpty() && 8861cb0ef41Sopenharmony_ci m_blackboxPattern->match(scriptSourceURL) != -1) 8871cb0ef41Sopenharmony_ci return true; 8881cb0ef41Sopenharmony_ci } 8891cb0ef41Sopenharmony_ci auto itBlackboxedPositions = m_blackboxedPositions.find(scriptId); 8901cb0ef41Sopenharmony_ci if (itBlackboxedPositions == m_blackboxedPositions.end()) return false; 8911cb0ef41Sopenharmony_ci 8921cb0ef41Sopenharmony_ci const std::vector<std::pair<int, int>>& ranges = 8931cb0ef41Sopenharmony_ci itBlackboxedPositions->second; 8941cb0ef41Sopenharmony_ci auto itStartRange = std::lower_bound( 8951cb0ef41Sopenharmony_ci ranges.begin(), ranges.end(), 8961cb0ef41Sopenharmony_ci std::make_pair(start.GetLineNumber(), start.GetColumnNumber()), 8971cb0ef41Sopenharmony_ci positionComparator); 8981cb0ef41Sopenharmony_ci auto itEndRange = std::lower_bound( 8991cb0ef41Sopenharmony_ci itStartRange, ranges.end(), 9001cb0ef41Sopenharmony_ci std::make_pair(end.GetLineNumber(), end.GetColumnNumber()), 9011cb0ef41Sopenharmony_ci positionComparator); 9021cb0ef41Sopenharmony_ci // Ranges array contains positions in script where blackbox state is changed. 9031cb0ef41Sopenharmony_ci // [(0,0) ... ranges[0]) isn't blackboxed, [ranges[0] ... ranges[1]) is 9041cb0ef41Sopenharmony_ci // blackboxed... 9051cb0ef41Sopenharmony_ci return itStartRange == itEndRange && 9061cb0ef41Sopenharmony_ci std::distance(ranges.begin(), itStartRange) % 2; 9071cb0ef41Sopenharmony_ci} 9081cb0ef41Sopenharmony_ci 9091cb0ef41Sopenharmony_cibool V8DebuggerAgentImpl::shouldBeSkipped(const String16& scriptId, int line, 9101cb0ef41Sopenharmony_ci int column) { 9111cb0ef41Sopenharmony_ci if (m_skipList.empty()) return false; 9121cb0ef41Sopenharmony_ci 9131cb0ef41Sopenharmony_ci auto it = m_skipList.find(scriptId); 9141cb0ef41Sopenharmony_ci if (it == m_skipList.end()) return false; 9151cb0ef41Sopenharmony_ci 9161cb0ef41Sopenharmony_ci const std::vector<std::pair<int, int>>& ranges = it->second; 9171cb0ef41Sopenharmony_ci DCHECK(!ranges.empty()); 9181cb0ef41Sopenharmony_ci const std::pair<int, int> location = std::make_pair(line, column); 9191cb0ef41Sopenharmony_ci auto itLowerBound = std::lower_bound(ranges.begin(), ranges.end(), location, 9201cb0ef41Sopenharmony_ci positionComparator); 9211cb0ef41Sopenharmony_ci 9221cb0ef41Sopenharmony_ci bool shouldSkip = false; 9231cb0ef41Sopenharmony_ci if (itLowerBound != ranges.end()) { 9241cb0ef41Sopenharmony_ci // Skip lists are defined as pairs of locations that specify the 9251cb0ef41Sopenharmony_ci // start and the end of ranges to skip: [ranges[0], ranges[1], ..], where 9261cb0ef41Sopenharmony_ci // locations in [ranges[0], ranges[1]) should be skipped, i.e. 9271cb0ef41Sopenharmony_ci // [(lineStart, columnStart), (lineEnd, columnEnd)). 9281cb0ef41Sopenharmony_ci const bool isSameAsLowerBound = location == *itLowerBound; 9291cb0ef41Sopenharmony_ci const bool isUnevenIndex = (itLowerBound - ranges.begin()) % 2; 9301cb0ef41Sopenharmony_ci shouldSkip = isSameAsLowerBound ^ isUnevenIndex; 9311cb0ef41Sopenharmony_ci } 9321cb0ef41Sopenharmony_ci 9331cb0ef41Sopenharmony_ci return shouldSkip; 9341cb0ef41Sopenharmony_ci} 9351cb0ef41Sopenharmony_ci 9361cb0ef41Sopenharmony_cibool V8DebuggerAgentImpl::acceptsPause(bool isOOMBreak) const { 9371cb0ef41Sopenharmony_ci return enabled() && (isOOMBreak || !m_skipAllPauses); 9381cb0ef41Sopenharmony_ci} 9391cb0ef41Sopenharmony_ci 9401cb0ef41Sopenharmony_cistd::unique_ptr<protocol::Debugger::Location> 9411cb0ef41Sopenharmony_ciV8DebuggerAgentImpl::setBreakpointImpl(const String16& breakpointId, 9421cb0ef41Sopenharmony_ci const String16& scriptId, 9431cb0ef41Sopenharmony_ci const String16& condition, 9441cb0ef41Sopenharmony_ci int lineNumber, int columnNumber) { 9451cb0ef41Sopenharmony_ci v8::HandleScope handles(m_isolate); 9461cb0ef41Sopenharmony_ci DCHECK(enabled()); 9471cb0ef41Sopenharmony_ci 9481cb0ef41Sopenharmony_ci ScriptsMap::iterator scriptIterator = m_scripts.find(scriptId); 9491cb0ef41Sopenharmony_ci if (scriptIterator == m_scripts.end()) return nullptr; 9501cb0ef41Sopenharmony_ci V8DebuggerScript* script = scriptIterator->second.get(); 9511cb0ef41Sopenharmony_ci if (lineNumber < script->startLine() || script->endLine() < lineNumber) { 9521cb0ef41Sopenharmony_ci return nullptr; 9531cb0ef41Sopenharmony_ci } 9541cb0ef41Sopenharmony_ci if (lineNumber == script->startLine() && 9551cb0ef41Sopenharmony_ci columnNumber < script->startColumn()) { 9561cb0ef41Sopenharmony_ci return nullptr; 9571cb0ef41Sopenharmony_ci } 9581cb0ef41Sopenharmony_ci if (lineNumber == script->endLine() && script->endColumn() < columnNumber) { 9591cb0ef41Sopenharmony_ci return nullptr; 9601cb0ef41Sopenharmony_ci } 9611cb0ef41Sopenharmony_ci 9621cb0ef41Sopenharmony_ci v8::debug::BreakpointId debuggerBreakpointId; 9631cb0ef41Sopenharmony_ci v8::debug::Location location(lineNumber, columnNumber); 9641cb0ef41Sopenharmony_ci int contextId = script->executionContextId(); 9651cb0ef41Sopenharmony_ci InspectedContext* inspected = m_inspector->getContext(contextId); 9661cb0ef41Sopenharmony_ci if (!inspected) return nullptr; 9671cb0ef41Sopenharmony_ci 9681cb0ef41Sopenharmony_ci { 9691cb0ef41Sopenharmony_ci v8::Context::Scope contextScope(inspected->context()); 9701cb0ef41Sopenharmony_ci if (!script->setBreakpoint(condition, &location, &debuggerBreakpointId)) { 9711cb0ef41Sopenharmony_ci return nullptr; 9721cb0ef41Sopenharmony_ci } 9731cb0ef41Sopenharmony_ci } 9741cb0ef41Sopenharmony_ci 9751cb0ef41Sopenharmony_ci m_debuggerBreakpointIdToBreakpointId[debuggerBreakpointId] = breakpointId; 9761cb0ef41Sopenharmony_ci m_breakpointIdToDebuggerBreakpointIds[breakpointId].push_back( 9771cb0ef41Sopenharmony_ci debuggerBreakpointId); 9781cb0ef41Sopenharmony_ci 9791cb0ef41Sopenharmony_ci return protocol::Debugger::Location::create() 9801cb0ef41Sopenharmony_ci .setScriptId(scriptId) 9811cb0ef41Sopenharmony_ci .setLineNumber(location.GetLineNumber()) 9821cb0ef41Sopenharmony_ci .setColumnNumber(location.GetColumnNumber()) 9831cb0ef41Sopenharmony_ci .build(); 9841cb0ef41Sopenharmony_ci} 9851cb0ef41Sopenharmony_ci 9861cb0ef41Sopenharmony_civoid V8DebuggerAgentImpl::setBreakpointImpl(const String16& breakpointId, 9871cb0ef41Sopenharmony_ci v8::Local<v8::Function> function, 9881cb0ef41Sopenharmony_ci v8::Local<v8::String> condition) { 9891cb0ef41Sopenharmony_ci v8::debug::BreakpointId debuggerBreakpointId; 9901cb0ef41Sopenharmony_ci if (!v8::debug::SetFunctionBreakpoint(function, condition, 9911cb0ef41Sopenharmony_ci &debuggerBreakpointId)) { 9921cb0ef41Sopenharmony_ci return; 9931cb0ef41Sopenharmony_ci } 9941cb0ef41Sopenharmony_ci m_debuggerBreakpointIdToBreakpointId[debuggerBreakpointId] = breakpointId; 9951cb0ef41Sopenharmony_ci m_breakpointIdToDebuggerBreakpointIds[breakpointId].push_back( 9961cb0ef41Sopenharmony_ci debuggerBreakpointId); 9971cb0ef41Sopenharmony_ci} 9981cb0ef41Sopenharmony_ci 9991cb0ef41Sopenharmony_ciResponse V8DebuggerAgentImpl::searchInContent( 10001cb0ef41Sopenharmony_ci const String16& scriptId, const String16& query, 10011cb0ef41Sopenharmony_ci Maybe<bool> optionalCaseSensitive, Maybe<bool> optionalIsRegex, 10021cb0ef41Sopenharmony_ci std::unique_ptr<Array<protocol::Debugger::SearchMatch>>* results) { 10031cb0ef41Sopenharmony_ci v8::HandleScope handles(m_isolate); 10041cb0ef41Sopenharmony_ci ScriptsMap::iterator it = m_scripts.find(scriptId); 10051cb0ef41Sopenharmony_ci if (it == m_scripts.end()) 10061cb0ef41Sopenharmony_ci return Response::ServerError("No script for id: " + scriptId.utf8()); 10071cb0ef41Sopenharmony_ci 10081cb0ef41Sopenharmony_ci *results = std::make_unique<protocol::Array<protocol::Debugger::SearchMatch>>( 10091cb0ef41Sopenharmony_ci searchInTextByLinesImpl(m_session, it->second->source(0), query, 10101cb0ef41Sopenharmony_ci optionalCaseSensitive.fromMaybe(false), 10111cb0ef41Sopenharmony_ci optionalIsRegex.fromMaybe(false))); 10121cb0ef41Sopenharmony_ci return Response::Success(); 10131cb0ef41Sopenharmony_ci} 10141cb0ef41Sopenharmony_ci 10151cb0ef41Sopenharmony_ciResponse V8DebuggerAgentImpl::setScriptSource( 10161cb0ef41Sopenharmony_ci const String16& scriptId, const String16& newContent, Maybe<bool> dryRun, 10171cb0ef41Sopenharmony_ci Maybe<protocol::Array<protocol::Debugger::CallFrame>>* newCallFrames, 10181cb0ef41Sopenharmony_ci Maybe<bool>* stackChanged, 10191cb0ef41Sopenharmony_ci Maybe<protocol::Runtime::StackTrace>* asyncStackTrace, 10201cb0ef41Sopenharmony_ci Maybe<protocol::Runtime::StackTraceId>* asyncStackTraceId, 10211cb0ef41Sopenharmony_ci Maybe<protocol::Runtime::ExceptionDetails>* optOutCompileError) { 10221cb0ef41Sopenharmony_ci if (!enabled()) return Response::ServerError(kDebuggerNotEnabled); 10231cb0ef41Sopenharmony_ci 10241cb0ef41Sopenharmony_ci ScriptsMap::iterator it = m_scripts.find(scriptId); 10251cb0ef41Sopenharmony_ci if (it == m_scripts.end()) { 10261cb0ef41Sopenharmony_ci return Response::ServerError("No script with given id found"); 10271cb0ef41Sopenharmony_ci } 10281cb0ef41Sopenharmony_ci int contextId = it->second->executionContextId(); 10291cb0ef41Sopenharmony_ci InspectedContext* inspected = m_inspector->getContext(contextId); 10301cb0ef41Sopenharmony_ci if (!inspected) { 10311cb0ef41Sopenharmony_ci return Response::InternalError(); 10321cb0ef41Sopenharmony_ci } 10331cb0ef41Sopenharmony_ci v8::HandleScope handleScope(m_isolate); 10341cb0ef41Sopenharmony_ci v8::Local<v8::Context> context = inspected->context(); 10351cb0ef41Sopenharmony_ci v8::Context::Scope contextScope(context); 10361cb0ef41Sopenharmony_ci 10371cb0ef41Sopenharmony_ci v8::debug::LiveEditResult result; 10381cb0ef41Sopenharmony_ci it->second->setSource(newContent, dryRun.fromMaybe(false), &result); 10391cb0ef41Sopenharmony_ci if (result.status != v8::debug::LiveEditResult::OK) { 10401cb0ef41Sopenharmony_ci *optOutCompileError = 10411cb0ef41Sopenharmony_ci protocol::Runtime::ExceptionDetails::create() 10421cb0ef41Sopenharmony_ci .setExceptionId(m_inspector->nextExceptionId()) 10431cb0ef41Sopenharmony_ci .setText(toProtocolString(m_isolate, result.message)) 10441cb0ef41Sopenharmony_ci .setLineNumber(result.line_number != -1 ? result.line_number - 1 10451cb0ef41Sopenharmony_ci : 0) 10461cb0ef41Sopenharmony_ci .setColumnNumber(result.column_number != -1 ? result.column_number 10471cb0ef41Sopenharmony_ci : 0) 10481cb0ef41Sopenharmony_ci .build(); 10491cb0ef41Sopenharmony_ci return Response::Success(); 10501cb0ef41Sopenharmony_ci } else { 10511cb0ef41Sopenharmony_ci *stackChanged = result.stack_changed; 10521cb0ef41Sopenharmony_ci } 10531cb0ef41Sopenharmony_ci std::unique_ptr<Array<CallFrame>> callFrames; 10541cb0ef41Sopenharmony_ci Response response = currentCallFrames(&callFrames); 10551cb0ef41Sopenharmony_ci if (!response.IsSuccess()) return response; 10561cb0ef41Sopenharmony_ci *newCallFrames = std::move(callFrames); 10571cb0ef41Sopenharmony_ci *asyncStackTrace = currentAsyncStackTrace(); 10581cb0ef41Sopenharmony_ci *asyncStackTraceId = currentExternalStackTrace(); 10591cb0ef41Sopenharmony_ci return Response::Success(); 10601cb0ef41Sopenharmony_ci} 10611cb0ef41Sopenharmony_ci 10621cb0ef41Sopenharmony_ciResponse V8DebuggerAgentImpl::restartFrame( 10631cb0ef41Sopenharmony_ci const String16& callFrameId, 10641cb0ef41Sopenharmony_ci std::unique_ptr<Array<CallFrame>>* newCallFrames, 10651cb0ef41Sopenharmony_ci Maybe<protocol::Runtime::StackTrace>* asyncStackTrace, 10661cb0ef41Sopenharmony_ci Maybe<protocol::Runtime::StackTraceId>* asyncStackTraceId) { 10671cb0ef41Sopenharmony_ci return Response::ServerError("Frame restarting not supported"); 10681cb0ef41Sopenharmony_ci} 10691cb0ef41Sopenharmony_ci 10701cb0ef41Sopenharmony_ciResponse V8DebuggerAgentImpl::getScriptSource( 10711cb0ef41Sopenharmony_ci const String16& scriptId, String16* scriptSource, 10721cb0ef41Sopenharmony_ci Maybe<protocol::Binary>* bytecode) { 10731cb0ef41Sopenharmony_ci if (!enabled()) return Response::ServerError(kDebuggerNotEnabled); 10741cb0ef41Sopenharmony_ci ScriptsMap::iterator it = m_scripts.find(scriptId); 10751cb0ef41Sopenharmony_ci if (it == m_scripts.end()) { 10761cb0ef41Sopenharmony_ci auto cachedScriptIt = 10771cb0ef41Sopenharmony_ci std::find_if(m_cachedScripts.begin(), m_cachedScripts.end(), 10781cb0ef41Sopenharmony_ci [&scriptId](const CachedScript& cachedScript) { 10791cb0ef41Sopenharmony_ci return cachedScript.scriptId == scriptId; 10801cb0ef41Sopenharmony_ci }); 10811cb0ef41Sopenharmony_ci if (cachedScriptIt != m_cachedScripts.end()) { 10821cb0ef41Sopenharmony_ci *scriptSource = cachedScriptIt->source; 10831cb0ef41Sopenharmony_ci *bytecode = protocol::Binary::fromSpan(cachedScriptIt->bytecode.data(), 10841cb0ef41Sopenharmony_ci cachedScriptIt->bytecode.size()); 10851cb0ef41Sopenharmony_ci return Response::Success(); 10861cb0ef41Sopenharmony_ci } 10871cb0ef41Sopenharmony_ci return Response::ServerError("No script for id: " + scriptId.utf8()); 10881cb0ef41Sopenharmony_ci } 10891cb0ef41Sopenharmony_ci *scriptSource = it->second->source(0); 10901cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY 10911cb0ef41Sopenharmony_ci v8::MemorySpan<const uint8_t> span; 10921cb0ef41Sopenharmony_ci if (it->second->wasmBytecode().To(&span)) { 10931cb0ef41Sopenharmony_ci if (span.size() > kWasmBytecodeMaxLength) { 10941cb0ef41Sopenharmony_ci return Response::ServerError(kWasmBytecodeExceedsTransferLimit); 10951cb0ef41Sopenharmony_ci } 10961cb0ef41Sopenharmony_ci *bytecode = protocol::Binary::fromSpan(span.data(), span.size()); 10971cb0ef41Sopenharmony_ci } 10981cb0ef41Sopenharmony_ci#endif // V8_ENABLE_WEBASSEMBLY 10991cb0ef41Sopenharmony_ci return Response::Success(); 11001cb0ef41Sopenharmony_ci} 11011cb0ef41Sopenharmony_ci 11021cb0ef41Sopenharmony_ciResponse V8DebuggerAgentImpl::getWasmBytecode(const String16& scriptId, 11031cb0ef41Sopenharmony_ci protocol::Binary* bytecode) { 11041cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY 11051cb0ef41Sopenharmony_ci if (!enabled()) return Response::ServerError(kDebuggerNotEnabled); 11061cb0ef41Sopenharmony_ci ScriptsMap::iterator it = m_scripts.find(scriptId); 11071cb0ef41Sopenharmony_ci if (it == m_scripts.end()) 11081cb0ef41Sopenharmony_ci return Response::ServerError("No script for id: " + scriptId.utf8()); 11091cb0ef41Sopenharmony_ci v8::MemorySpan<const uint8_t> span; 11101cb0ef41Sopenharmony_ci if (!it->second->wasmBytecode().To(&span)) 11111cb0ef41Sopenharmony_ci return Response::ServerError("Script with id " + scriptId.utf8() + 11121cb0ef41Sopenharmony_ci " is not WebAssembly"); 11131cb0ef41Sopenharmony_ci if (span.size() > kWasmBytecodeMaxLength) { 11141cb0ef41Sopenharmony_ci return Response::ServerError(kWasmBytecodeExceedsTransferLimit); 11151cb0ef41Sopenharmony_ci } 11161cb0ef41Sopenharmony_ci *bytecode = protocol::Binary::fromSpan(span.data(), span.size()); 11171cb0ef41Sopenharmony_ci return Response::Success(); 11181cb0ef41Sopenharmony_ci#else 11191cb0ef41Sopenharmony_ci return Response::ServerError("WebAssembly is disabled"); 11201cb0ef41Sopenharmony_ci#endif // V8_ENABLE_WEBASSEMBLY 11211cb0ef41Sopenharmony_ci} 11221cb0ef41Sopenharmony_ci 11231cb0ef41Sopenharmony_civoid V8DebuggerAgentImpl::pushBreakDetails( 11241cb0ef41Sopenharmony_ci const String16& breakReason, 11251cb0ef41Sopenharmony_ci std::unique_ptr<protocol::DictionaryValue> breakAuxData) { 11261cb0ef41Sopenharmony_ci m_breakReason.push_back(std::make_pair(breakReason, std::move(breakAuxData))); 11271cb0ef41Sopenharmony_ci} 11281cb0ef41Sopenharmony_ci 11291cb0ef41Sopenharmony_civoid V8DebuggerAgentImpl::popBreakDetails() { 11301cb0ef41Sopenharmony_ci if (m_breakReason.empty()) return; 11311cb0ef41Sopenharmony_ci m_breakReason.pop_back(); 11321cb0ef41Sopenharmony_ci} 11331cb0ef41Sopenharmony_ci 11341cb0ef41Sopenharmony_civoid V8DebuggerAgentImpl::clearBreakDetails() { 11351cb0ef41Sopenharmony_ci std::vector<BreakReason> emptyBreakReason; 11361cb0ef41Sopenharmony_ci m_breakReason.swap(emptyBreakReason); 11371cb0ef41Sopenharmony_ci} 11381cb0ef41Sopenharmony_ci 11391cb0ef41Sopenharmony_civoid V8DebuggerAgentImpl::schedulePauseOnNextStatement( 11401cb0ef41Sopenharmony_ci const String16& breakReason, 11411cb0ef41Sopenharmony_ci std::unique_ptr<protocol::DictionaryValue> data) { 11421cb0ef41Sopenharmony_ci if (isPaused() || !acceptsPause(false) || !m_breakpointsActive) return; 11431cb0ef41Sopenharmony_ci if (m_breakReason.empty()) { 11441cb0ef41Sopenharmony_ci m_debugger->setPauseOnNextCall(true, m_session->contextGroupId()); 11451cb0ef41Sopenharmony_ci } 11461cb0ef41Sopenharmony_ci pushBreakDetails(breakReason, std::move(data)); 11471cb0ef41Sopenharmony_ci} 11481cb0ef41Sopenharmony_ci 11491cb0ef41Sopenharmony_civoid V8DebuggerAgentImpl::cancelPauseOnNextStatement() { 11501cb0ef41Sopenharmony_ci if (isPaused() || !acceptsPause(false) || !m_breakpointsActive) return; 11511cb0ef41Sopenharmony_ci if (m_breakReason.size() == 1) { 11521cb0ef41Sopenharmony_ci m_debugger->setPauseOnNextCall(false, m_session->contextGroupId()); 11531cb0ef41Sopenharmony_ci } 11541cb0ef41Sopenharmony_ci popBreakDetails(); 11551cb0ef41Sopenharmony_ci} 11561cb0ef41Sopenharmony_ci 11571cb0ef41Sopenharmony_ciResponse V8DebuggerAgentImpl::pause() { 11581cb0ef41Sopenharmony_ci if (!enabled()) return Response::ServerError(kDebuggerNotEnabled); 11591cb0ef41Sopenharmony_ci if (isPaused()) return Response::Success(); 11601cb0ef41Sopenharmony_ci 11611cb0ef41Sopenharmony_ci if (m_debugger->canBreakProgram()) { 11621cb0ef41Sopenharmony_ci m_debugger->interruptAndBreak(m_session->contextGroupId()); 11631cb0ef41Sopenharmony_ci } else { 11641cb0ef41Sopenharmony_ci pushBreakDetails(protocol::Debugger::Paused::ReasonEnum::Other, nullptr); 11651cb0ef41Sopenharmony_ci m_debugger->setPauseOnNextCall(true, m_session->contextGroupId()); 11661cb0ef41Sopenharmony_ci } 11671cb0ef41Sopenharmony_ci 11681cb0ef41Sopenharmony_ci return Response::Success(); 11691cb0ef41Sopenharmony_ci} 11701cb0ef41Sopenharmony_ci 11711cb0ef41Sopenharmony_ciResponse V8DebuggerAgentImpl::resume(Maybe<bool> terminateOnResume) { 11721cb0ef41Sopenharmony_ci if (!isPaused()) return Response::ServerError(kDebuggerNotPaused); 11731cb0ef41Sopenharmony_ci m_session->releaseObjectGroup(kBacktraceObjectGroup); 11741cb0ef41Sopenharmony_ci m_debugger->continueProgram(m_session->contextGroupId(), 11751cb0ef41Sopenharmony_ci terminateOnResume.fromMaybe(false)); 11761cb0ef41Sopenharmony_ci return Response::Success(); 11771cb0ef41Sopenharmony_ci} 11781cb0ef41Sopenharmony_ci 11791cb0ef41Sopenharmony_ciResponse V8DebuggerAgentImpl::stepOver( 11801cb0ef41Sopenharmony_ci Maybe<protocol::Array<protocol::Debugger::LocationRange>> inSkipList) { 11811cb0ef41Sopenharmony_ci if (!isPaused()) return Response::ServerError(kDebuggerNotPaused); 11821cb0ef41Sopenharmony_ci 11831cb0ef41Sopenharmony_ci if (inSkipList.isJust()) { 11841cb0ef41Sopenharmony_ci const Response res = processSkipList(inSkipList.fromJust()); 11851cb0ef41Sopenharmony_ci if (res.IsError()) return res; 11861cb0ef41Sopenharmony_ci } else { 11871cb0ef41Sopenharmony_ci m_skipList.clear(); 11881cb0ef41Sopenharmony_ci } 11891cb0ef41Sopenharmony_ci 11901cb0ef41Sopenharmony_ci m_session->releaseObjectGroup(kBacktraceObjectGroup); 11911cb0ef41Sopenharmony_ci m_debugger->stepOverStatement(m_session->contextGroupId()); 11921cb0ef41Sopenharmony_ci return Response::Success(); 11931cb0ef41Sopenharmony_ci} 11941cb0ef41Sopenharmony_ci 11951cb0ef41Sopenharmony_ciResponse V8DebuggerAgentImpl::stepInto( 11961cb0ef41Sopenharmony_ci Maybe<bool> inBreakOnAsyncCall, 11971cb0ef41Sopenharmony_ci Maybe<protocol::Array<protocol::Debugger::LocationRange>> inSkipList) { 11981cb0ef41Sopenharmony_ci if (!isPaused()) return Response::ServerError(kDebuggerNotPaused); 11991cb0ef41Sopenharmony_ci 12001cb0ef41Sopenharmony_ci if (inSkipList.isJust()) { 12011cb0ef41Sopenharmony_ci const Response res = processSkipList(inSkipList.fromJust()); 12021cb0ef41Sopenharmony_ci if (res.IsError()) return res; 12031cb0ef41Sopenharmony_ci } else { 12041cb0ef41Sopenharmony_ci m_skipList.clear(); 12051cb0ef41Sopenharmony_ci } 12061cb0ef41Sopenharmony_ci 12071cb0ef41Sopenharmony_ci m_session->releaseObjectGroup(kBacktraceObjectGroup); 12081cb0ef41Sopenharmony_ci m_debugger->stepIntoStatement(m_session->contextGroupId(), 12091cb0ef41Sopenharmony_ci inBreakOnAsyncCall.fromMaybe(false)); 12101cb0ef41Sopenharmony_ci return Response::Success(); 12111cb0ef41Sopenharmony_ci} 12121cb0ef41Sopenharmony_ci 12131cb0ef41Sopenharmony_ciResponse V8DebuggerAgentImpl::stepOut() { 12141cb0ef41Sopenharmony_ci if (!isPaused()) return Response::ServerError(kDebuggerNotPaused); 12151cb0ef41Sopenharmony_ci m_session->releaseObjectGroup(kBacktraceObjectGroup); 12161cb0ef41Sopenharmony_ci m_debugger->stepOutOfFunction(m_session->contextGroupId()); 12171cb0ef41Sopenharmony_ci return Response::Success(); 12181cb0ef41Sopenharmony_ci} 12191cb0ef41Sopenharmony_ci 12201cb0ef41Sopenharmony_ciResponse V8DebuggerAgentImpl::pauseOnAsyncCall( 12211cb0ef41Sopenharmony_ci std::unique_ptr<protocol::Runtime::StackTraceId> inParentStackTraceId) { 12221cb0ef41Sopenharmony_ci // Deprecated, just return OK. 12231cb0ef41Sopenharmony_ci return Response::Success(); 12241cb0ef41Sopenharmony_ci} 12251cb0ef41Sopenharmony_ci 12261cb0ef41Sopenharmony_ciResponse V8DebuggerAgentImpl::setPauseOnExceptions( 12271cb0ef41Sopenharmony_ci const String16& stringPauseState) { 12281cb0ef41Sopenharmony_ci if (!enabled()) return Response::ServerError(kDebuggerNotEnabled); 12291cb0ef41Sopenharmony_ci v8::debug::ExceptionBreakState pauseState; 12301cb0ef41Sopenharmony_ci if (stringPauseState == "none") { 12311cb0ef41Sopenharmony_ci pauseState = v8::debug::NoBreakOnException; 12321cb0ef41Sopenharmony_ci } else if (stringPauseState == "all") { 12331cb0ef41Sopenharmony_ci pauseState = v8::debug::BreakOnAnyException; 12341cb0ef41Sopenharmony_ci } else if (stringPauseState == "uncaught") { 12351cb0ef41Sopenharmony_ci pauseState = v8::debug::BreakOnUncaughtException; 12361cb0ef41Sopenharmony_ci } else { 12371cb0ef41Sopenharmony_ci return Response::ServerError("Unknown pause on exceptions mode: " + 12381cb0ef41Sopenharmony_ci stringPauseState.utf8()); 12391cb0ef41Sopenharmony_ci } 12401cb0ef41Sopenharmony_ci setPauseOnExceptionsImpl(pauseState); 12411cb0ef41Sopenharmony_ci return Response::Success(); 12421cb0ef41Sopenharmony_ci} 12431cb0ef41Sopenharmony_ci 12441cb0ef41Sopenharmony_civoid V8DebuggerAgentImpl::setPauseOnExceptionsImpl(int pauseState) { 12451cb0ef41Sopenharmony_ci // TODO(dgozman): this changes the global state and forces all context groups 12461cb0ef41Sopenharmony_ci // to pause. We should make this flag be per-context-group. 12471cb0ef41Sopenharmony_ci m_debugger->setPauseOnExceptionsState( 12481cb0ef41Sopenharmony_ci static_cast<v8::debug::ExceptionBreakState>(pauseState)); 12491cb0ef41Sopenharmony_ci m_state->setInteger(DebuggerAgentState::pauseOnExceptionsState, pauseState); 12501cb0ef41Sopenharmony_ci} 12511cb0ef41Sopenharmony_ci 12521cb0ef41Sopenharmony_ciResponse V8DebuggerAgentImpl::evaluateOnCallFrame( 12531cb0ef41Sopenharmony_ci const String16& callFrameId, const String16& expression, 12541cb0ef41Sopenharmony_ci Maybe<String16> objectGroup, Maybe<bool> includeCommandLineAPI, 12551cb0ef41Sopenharmony_ci Maybe<bool> silent, Maybe<bool> returnByValue, Maybe<bool> generatePreview, 12561cb0ef41Sopenharmony_ci Maybe<bool> throwOnSideEffect, Maybe<double> timeout, 12571cb0ef41Sopenharmony_ci std::unique_ptr<RemoteObject>* result, 12581cb0ef41Sopenharmony_ci Maybe<protocol::Runtime::ExceptionDetails>* exceptionDetails) { 12591cb0ef41Sopenharmony_ci if (!isPaused()) return Response::ServerError(kDebuggerNotPaused); 12601cb0ef41Sopenharmony_ci InjectedScript::CallFrameScope scope(m_session, callFrameId); 12611cb0ef41Sopenharmony_ci Response response = scope.initialize(); 12621cb0ef41Sopenharmony_ci if (!response.IsSuccess()) return response; 12631cb0ef41Sopenharmony_ci if (includeCommandLineAPI.fromMaybe(false)) scope.installCommandLineAPI(); 12641cb0ef41Sopenharmony_ci if (silent.fromMaybe(false)) scope.ignoreExceptionsAndMuteConsole(); 12651cb0ef41Sopenharmony_ci 12661cb0ef41Sopenharmony_ci int frameOrdinal = static_cast<int>(scope.frameOrdinal()); 12671cb0ef41Sopenharmony_ci auto it = v8::debug::StackTraceIterator::Create(m_isolate, frameOrdinal); 12681cb0ef41Sopenharmony_ci if (it->Done()) { 12691cb0ef41Sopenharmony_ci return Response::ServerError("Could not find call frame with given id"); 12701cb0ef41Sopenharmony_ci } 12711cb0ef41Sopenharmony_ci 12721cb0ef41Sopenharmony_ci v8::MaybeLocal<v8::Value> maybeResultValue; 12731cb0ef41Sopenharmony_ci { 12741cb0ef41Sopenharmony_ci V8InspectorImpl::EvaluateScope evaluateScope(scope); 12751cb0ef41Sopenharmony_ci if (timeout.isJust()) { 12761cb0ef41Sopenharmony_ci response = evaluateScope.setTimeout(timeout.fromJust() / 1000.0); 12771cb0ef41Sopenharmony_ci if (!response.IsSuccess()) return response; 12781cb0ef41Sopenharmony_ci } 12791cb0ef41Sopenharmony_ci maybeResultValue = it->Evaluate(toV8String(m_isolate, expression), 12801cb0ef41Sopenharmony_ci throwOnSideEffect.fromMaybe(false)); 12811cb0ef41Sopenharmony_ci } 12821cb0ef41Sopenharmony_ci // Re-initialize after running client's code, as it could have destroyed 12831cb0ef41Sopenharmony_ci // context or session. 12841cb0ef41Sopenharmony_ci response = scope.initialize(); 12851cb0ef41Sopenharmony_ci if (!response.IsSuccess()) return response; 12861cb0ef41Sopenharmony_ci WrapMode mode = generatePreview.fromMaybe(false) ? WrapMode::kWithPreview 12871cb0ef41Sopenharmony_ci : WrapMode::kNoPreview; 12881cb0ef41Sopenharmony_ci if (returnByValue.fromMaybe(false)) mode = WrapMode::kForceValue; 12891cb0ef41Sopenharmony_ci return scope.injectedScript()->wrapEvaluateResult( 12901cb0ef41Sopenharmony_ci maybeResultValue, scope.tryCatch(), objectGroup.fromMaybe(""), mode, 12911cb0ef41Sopenharmony_ci result, exceptionDetails); 12921cb0ef41Sopenharmony_ci} 12931cb0ef41Sopenharmony_ci 12941cb0ef41Sopenharmony_ciResponse V8DebuggerAgentImpl::setVariableValue( 12951cb0ef41Sopenharmony_ci int scopeNumber, const String16& variableName, 12961cb0ef41Sopenharmony_ci std::unique_ptr<protocol::Runtime::CallArgument> newValueArgument, 12971cb0ef41Sopenharmony_ci const String16& callFrameId) { 12981cb0ef41Sopenharmony_ci if (!enabled()) return Response::ServerError(kDebuggerNotEnabled); 12991cb0ef41Sopenharmony_ci if (!isPaused()) return Response::ServerError(kDebuggerNotPaused); 13001cb0ef41Sopenharmony_ci InjectedScript::CallFrameScope scope(m_session, callFrameId); 13011cb0ef41Sopenharmony_ci Response response = scope.initialize(); 13021cb0ef41Sopenharmony_ci if (!response.IsSuccess()) return response; 13031cb0ef41Sopenharmony_ci v8::Local<v8::Value> newValue; 13041cb0ef41Sopenharmony_ci response = scope.injectedScript()->resolveCallArgument(newValueArgument.get(), 13051cb0ef41Sopenharmony_ci &newValue); 13061cb0ef41Sopenharmony_ci if (!response.IsSuccess()) return response; 13071cb0ef41Sopenharmony_ci 13081cb0ef41Sopenharmony_ci int frameOrdinal = static_cast<int>(scope.frameOrdinal()); 13091cb0ef41Sopenharmony_ci auto it = v8::debug::StackTraceIterator::Create(m_isolate, frameOrdinal); 13101cb0ef41Sopenharmony_ci if (it->Done()) { 13111cb0ef41Sopenharmony_ci return Response::ServerError("Could not find call frame with given id"); 13121cb0ef41Sopenharmony_ci } 13131cb0ef41Sopenharmony_ci auto scopeIterator = it->GetScopeIterator(); 13141cb0ef41Sopenharmony_ci while (!scopeIterator->Done() && scopeNumber > 0) { 13151cb0ef41Sopenharmony_ci --scopeNumber; 13161cb0ef41Sopenharmony_ci scopeIterator->Advance(); 13171cb0ef41Sopenharmony_ci } 13181cb0ef41Sopenharmony_ci if (scopeNumber != 0) { 13191cb0ef41Sopenharmony_ci return Response::ServerError("Could not find scope with given number"); 13201cb0ef41Sopenharmony_ci } 13211cb0ef41Sopenharmony_ci 13221cb0ef41Sopenharmony_ci if (!scopeIterator->SetVariableValue(toV8String(m_isolate, variableName), 13231cb0ef41Sopenharmony_ci newValue) || 13241cb0ef41Sopenharmony_ci scope.tryCatch().HasCaught()) { 13251cb0ef41Sopenharmony_ci return Response::InternalError(); 13261cb0ef41Sopenharmony_ci } 13271cb0ef41Sopenharmony_ci return Response::Success(); 13281cb0ef41Sopenharmony_ci} 13291cb0ef41Sopenharmony_ci 13301cb0ef41Sopenharmony_ciResponse V8DebuggerAgentImpl::setReturnValue( 13311cb0ef41Sopenharmony_ci std::unique_ptr<protocol::Runtime::CallArgument> protocolNewValue) { 13321cb0ef41Sopenharmony_ci if (!enabled()) return Response::ServerError(kDebuggerNotEnabled); 13331cb0ef41Sopenharmony_ci if (!isPaused()) return Response::ServerError(kDebuggerNotPaused); 13341cb0ef41Sopenharmony_ci v8::HandleScope handleScope(m_isolate); 13351cb0ef41Sopenharmony_ci auto iterator = v8::debug::StackTraceIterator::Create(m_isolate); 13361cb0ef41Sopenharmony_ci if (iterator->Done()) { 13371cb0ef41Sopenharmony_ci return Response::ServerError("Could not find top call frame"); 13381cb0ef41Sopenharmony_ci } 13391cb0ef41Sopenharmony_ci if (iterator->GetReturnValue().IsEmpty()) { 13401cb0ef41Sopenharmony_ci return Response::ServerError( 13411cb0ef41Sopenharmony_ci "Could not update return value at non-return position"); 13421cb0ef41Sopenharmony_ci } 13431cb0ef41Sopenharmony_ci InjectedScript::ContextScope scope(m_session, iterator->GetContextId()); 13441cb0ef41Sopenharmony_ci Response response = scope.initialize(); 13451cb0ef41Sopenharmony_ci if (!response.IsSuccess()) return response; 13461cb0ef41Sopenharmony_ci v8::Local<v8::Value> newValue; 13471cb0ef41Sopenharmony_ci response = scope.injectedScript()->resolveCallArgument(protocolNewValue.get(), 13481cb0ef41Sopenharmony_ci &newValue); 13491cb0ef41Sopenharmony_ci if (!response.IsSuccess()) return response; 13501cb0ef41Sopenharmony_ci v8::debug::SetReturnValue(m_isolate, newValue); 13511cb0ef41Sopenharmony_ci return Response::Success(); 13521cb0ef41Sopenharmony_ci} 13531cb0ef41Sopenharmony_ci 13541cb0ef41Sopenharmony_ciResponse V8DebuggerAgentImpl::setAsyncCallStackDepth(int depth) { 13551cb0ef41Sopenharmony_ci if (!enabled() && !m_session->runtimeAgent()->enabled()) { 13561cb0ef41Sopenharmony_ci return Response::ServerError(kDebuggerNotEnabled); 13571cb0ef41Sopenharmony_ci } 13581cb0ef41Sopenharmony_ci m_state->setInteger(DebuggerAgentState::asyncCallStackDepth, depth); 13591cb0ef41Sopenharmony_ci m_debugger->setAsyncCallStackDepth(this, depth); 13601cb0ef41Sopenharmony_ci return Response::Success(); 13611cb0ef41Sopenharmony_ci} 13621cb0ef41Sopenharmony_ci 13631cb0ef41Sopenharmony_ciResponse V8DebuggerAgentImpl::setBlackboxPatterns( 13641cb0ef41Sopenharmony_ci std::unique_ptr<protocol::Array<String16>> patterns) { 13651cb0ef41Sopenharmony_ci if (patterns->empty()) { 13661cb0ef41Sopenharmony_ci m_blackboxPattern = nullptr; 13671cb0ef41Sopenharmony_ci resetBlackboxedStateCache(); 13681cb0ef41Sopenharmony_ci m_state->remove(DebuggerAgentState::blackboxPattern); 13691cb0ef41Sopenharmony_ci return Response::Success(); 13701cb0ef41Sopenharmony_ci } 13711cb0ef41Sopenharmony_ci 13721cb0ef41Sopenharmony_ci String16Builder patternBuilder; 13731cb0ef41Sopenharmony_ci patternBuilder.append('('); 13741cb0ef41Sopenharmony_ci for (size_t i = 0; i < patterns->size() - 1; ++i) { 13751cb0ef41Sopenharmony_ci patternBuilder.append((*patterns)[i]); 13761cb0ef41Sopenharmony_ci patternBuilder.append("|"); 13771cb0ef41Sopenharmony_ci } 13781cb0ef41Sopenharmony_ci patternBuilder.append(patterns->back()); 13791cb0ef41Sopenharmony_ci patternBuilder.append(')'); 13801cb0ef41Sopenharmony_ci String16 pattern = patternBuilder.toString(); 13811cb0ef41Sopenharmony_ci Response response = setBlackboxPattern(pattern); 13821cb0ef41Sopenharmony_ci if (!response.IsSuccess()) return response; 13831cb0ef41Sopenharmony_ci resetBlackboxedStateCache(); 13841cb0ef41Sopenharmony_ci m_state->setString(DebuggerAgentState::blackboxPattern, pattern); 13851cb0ef41Sopenharmony_ci return Response::Success(); 13861cb0ef41Sopenharmony_ci} 13871cb0ef41Sopenharmony_ci 13881cb0ef41Sopenharmony_ciResponse V8DebuggerAgentImpl::setBlackboxPattern(const String16& pattern) { 13891cb0ef41Sopenharmony_ci std::unique_ptr<V8Regex> regex(new V8Regex( 13901cb0ef41Sopenharmony_ci m_inspector, pattern, true /** caseSensitive */, false /** multiline */)); 13911cb0ef41Sopenharmony_ci if (!regex->isValid()) 13921cb0ef41Sopenharmony_ci return Response::ServerError("Pattern parser error: " + 13931cb0ef41Sopenharmony_ci regex->errorMessage().utf8()); 13941cb0ef41Sopenharmony_ci m_blackboxPattern = std::move(regex); 13951cb0ef41Sopenharmony_ci return Response::Success(); 13961cb0ef41Sopenharmony_ci} 13971cb0ef41Sopenharmony_ci 13981cb0ef41Sopenharmony_civoid V8DebuggerAgentImpl::resetBlackboxedStateCache() { 13991cb0ef41Sopenharmony_ci for (const auto& it : m_scripts) { 14001cb0ef41Sopenharmony_ci it.second->resetBlackboxedStateCache(); 14011cb0ef41Sopenharmony_ci } 14021cb0ef41Sopenharmony_ci} 14031cb0ef41Sopenharmony_ci 14041cb0ef41Sopenharmony_ciResponse V8DebuggerAgentImpl::setBlackboxedRanges( 14051cb0ef41Sopenharmony_ci const String16& scriptId, 14061cb0ef41Sopenharmony_ci std::unique_ptr<protocol::Array<protocol::Debugger::ScriptPosition>> 14071cb0ef41Sopenharmony_ci inPositions) { 14081cb0ef41Sopenharmony_ci auto it = m_scripts.find(scriptId); 14091cb0ef41Sopenharmony_ci if (it == m_scripts.end()) 14101cb0ef41Sopenharmony_ci return Response::ServerError("No script with passed id."); 14111cb0ef41Sopenharmony_ci 14121cb0ef41Sopenharmony_ci if (inPositions->empty()) { 14131cb0ef41Sopenharmony_ci m_blackboxedPositions.erase(scriptId); 14141cb0ef41Sopenharmony_ci it->second->resetBlackboxedStateCache(); 14151cb0ef41Sopenharmony_ci return Response::Success(); 14161cb0ef41Sopenharmony_ci } 14171cb0ef41Sopenharmony_ci 14181cb0ef41Sopenharmony_ci std::vector<std::pair<int, int>> positions; 14191cb0ef41Sopenharmony_ci positions.reserve(inPositions->size()); 14201cb0ef41Sopenharmony_ci for (const std::unique_ptr<protocol::Debugger::ScriptPosition>& position : 14211cb0ef41Sopenharmony_ci *inPositions) { 14221cb0ef41Sopenharmony_ci Response res = isValidPosition(position.get()); 14231cb0ef41Sopenharmony_ci if (res.IsError()) return res; 14241cb0ef41Sopenharmony_ci 14251cb0ef41Sopenharmony_ci positions.push_back( 14261cb0ef41Sopenharmony_ci std::make_pair(position->getLineNumber(), position->getColumnNumber())); 14271cb0ef41Sopenharmony_ci } 14281cb0ef41Sopenharmony_ci Response res = isValidRangeOfPositions(positions); 14291cb0ef41Sopenharmony_ci if (res.IsError()) return res; 14301cb0ef41Sopenharmony_ci 14311cb0ef41Sopenharmony_ci m_blackboxedPositions[scriptId] = positions; 14321cb0ef41Sopenharmony_ci it->second->resetBlackboxedStateCache(); 14331cb0ef41Sopenharmony_ci return Response::Success(); 14341cb0ef41Sopenharmony_ci} 14351cb0ef41Sopenharmony_ci 14361cb0ef41Sopenharmony_ciResponse V8DebuggerAgentImpl::currentCallFrames( 14371cb0ef41Sopenharmony_ci std::unique_ptr<Array<CallFrame>>* result) { 14381cb0ef41Sopenharmony_ci if (!isPaused()) { 14391cb0ef41Sopenharmony_ci *result = std::make_unique<Array<CallFrame>>(); 14401cb0ef41Sopenharmony_ci return Response::Success(); 14411cb0ef41Sopenharmony_ci } 14421cb0ef41Sopenharmony_ci v8::HandleScope handles(m_isolate); 14431cb0ef41Sopenharmony_ci *result = std::make_unique<Array<CallFrame>>(); 14441cb0ef41Sopenharmony_ci auto iterator = v8::debug::StackTraceIterator::Create(m_isolate); 14451cb0ef41Sopenharmony_ci int frameOrdinal = 0; 14461cb0ef41Sopenharmony_ci for (; !iterator->Done(); iterator->Advance(), frameOrdinal++) { 14471cb0ef41Sopenharmony_ci int contextId = iterator->GetContextId(); 14481cb0ef41Sopenharmony_ci InjectedScript* injectedScript = nullptr; 14491cb0ef41Sopenharmony_ci if (contextId) m_session->findInjectedScript(contextId, injectedScript); 14501cb0ef41Sopenharmony_ci String16 callFrameId = RemoteCallFrameId::serialize( 14511cb0ef41Sopenharmony_ci m_inspector->isolateId(), contextId, frameOrdinal); 14521cb0ef41Sopenharmony_ci 14531cb0ef41Sopenharmony_ci v8::debug::Location loc = iterator->GetSourceLocation(); 14541cb0ef41Sopenharmony_ci 14551cb0ef41Sopenharmony_ci std::unique_ptr<Array<Scope>> scopes; 14561cb0ef41Sopenharmony_ci auto scopeIterator = iterator->GetScopeIterator(); 14571cb0ef41Sopenharmony_ci Response res = 14581cb0ef41Sopenharmony_ci buildScopes(m_isolate, scopeIterator.get(), injectedScript, &scopes); 14591cb0ef41Sopenharmony_ci if (!res.IsSuccess()) return res; 14601cb0ef41Sopenharmony_ci 14611cb0ef41Sopenharmony_ci std::unique_ptr<RemoteObject> protocolReceiver; 14621cb0ef41Sopenharmony_ci if (injectedScript) { 14631cb0ef41Sopenharmony_ci v8::Local<v8::Value> receiver; 14641cb0ef41Sopenharmony_ci if (iterator->GetReceiver().ToLocal(&receiver)) { 14651cb0ef41Sopenharmony_ci res = 14661cb0ef41Sopenharmony_ci injectedScript->wrapObject(receiver, kBacktraceObjectGroup, 14671cb0ef41Sopenharmony_ci WrapMode::kNoPreview, &protocolReceiver); 14681cb0ef41Sopenharmony_ci if (!res.IsSuccess()) return res; 14691cb0ef41Sopenharmony_ci } 14701cb0ef41Sopenharmony_ci } 14711cb0ef41Sopenharmony_ci if (!protocolReceiver) { 14721cb0ef41Sopenharmony_ci protocolReceiver = RemoteObject::create() 14731cb0ef41Sopenharmony_ci .setType(RemoteObject::TypeEnum::Undefined) 14741cb0ef41Sopenharmony_ci .build(); 14751cb0ef41Sopenharmony_ci } 14761cb0ef41Sopenharmony_ci 14771cb0ef41Sopenharmony_ci v8::Local<v8::debug::Script> script = iterator->GetScript(); 14781cb0ef41Sopenharmony_ci DCHECK(!script.IsEmpty()); 14791cb0ef41Sopenharmony_ci std::unique_ptr<protocol::Debugger::Location> location = 14801cb0ef41Sopenharmony_ci protocol::Debugger::Location::create() 14811cb0ef41Sopenharmony_ci .setScriptId(String16::fromInteger(script->Id())) 14821cb0ef41Sopenharmony_ci .setLineNumber(loc.GetLineNumber()) 14831cb0ef41Sopenharmony_ci .setColumnNumber(loc.GetColumnNumber()) 14841cb0ef41Sopenharmony_ci .build(); 14851cb0ef41Sopenharmony_ci 14861cb0ef41Sopenharmony_ci auto frame = CallFrame::create() 14871cb0ef41Sopenharmony_ci .setCallFrameId(callFrameId) 14881cb0ef41Sopenharmony_ci .setFunctionName(toProtocolString( 14891cb0ef41Sopenharmony_ci m_isolate, iterator->GetFunctionDebugName())) 14901cb0ef41Sopenharmony_ci .setLocation(std::move(location)) 14911cb0ef41Sopenharmony_ci .setUrl(String16()) 14921cb0ef41Sopenharmony_ci .setScopeChain(std::move(scopes)) 14931cb0ef41Sopenharmony_ci .setThis(std::move(protocolReceiver)) 14941cb0ef41Sopenharmony_ci .build(); 14951cb0ef41Sopenharmony_ci 14961cb0ef41Sopenharmony_ci v8::Local<v8::Function> func = iterator->GetFunction(); 14971cb0ef41Sopenharmony_ci if (!func.IsEmpty()) { 14981cb0ef41Sopenharmony_ci frame->setFunctionLocation( 14991cb0ef41Sopenharmony_ci protocol::Debugger::Location::create() 15001cb0ef41Sopenharmony_ci .setScriptId(String16::fromInteger(func->ScriptId())) 15011cb0ef41Sopenharmony_ci .setLineNumber(func->GetScriptLineNumber()) 15021cb0ef41Sopenharmony_ci .setColumnNumber(func->GetScriptColumnNumber()) 15031cb0ef41Sopenharmony_ci .build()); 15041cb0ef41Sopenharmony_ci } 15051cb0ef41Sopenharmony_ci 15061cb0ef41Sopenharmony_ci v8::Local<v8::Value> returnValue = iterator->GetReturnValue(); 15071cb0ef41Sopenharmony_ci if (!returnValue.IsEmpty() && injectedScript) { 15081cb0ef41Sopenharmony_ci std::unique_ptr<RemoteObject> value; 15091cb0ef41Sopenharmony_ci res = injectedScript->wrapObject(returnValue, kBacktraceObjectGroup, 15101cb0ef41Sopenharmony_ci WrapMode::kNoPreview, &value); 15111cb0ef41Sopenharmony_ci if (!res.IsSuccess()) return res; 15121cb0ef41Sopenharmony_ci frame->setReturnValue(std::move(value)); 15131cb0ef41Sopenharmony_ci } 15141cb0ef41Sopenharmony_ci (*result)->emplace_back(std::move(frame)); 15151cb0ef41Sopenharmony_ci } 15161cb0ef41Sopenharmony_ci return Response::Success(); 15171cb0ef41Sopenharmony_ci} 15181cb0ef41Sopenharmony_ci 15191cb0ef41Sopenharmony_cistd::unique_ptr<protocol::Runtime::StackTrace> 15201cb0ef41Sopenharmony_ciV8DebuggerAgentImpl::currentAsyncStackTrace() { 15211cb0ef41Sopenharmony_ci std::shared_ptr<AsyncStackTrace> asyncParent = 15221cb0ef41Sopenharmony_ci m_debugger->currentAsyncParent(); 15231cb0ef41Sopenharmony_ci if (!asyncParent) return nullptr; 15241cb0ef41Sopenharmony_ci return asyncParent->buildInspectorObject( 15251cb0ef41Sopenharmony_ci m_debugger, m_debugger->maxAsyncCallChainDepth() - 1); 15261cb0ef41Sopenharmony_ci} 15271cb0ef41Sopenharmony_ci 15281cb0ef41Sopenharmony_cistd::unique_ptr<protocol::Runtime::StackTraceId> 15291cb0ef41Sopenharmony_ciV8DebuggerAgentImpl::currentExternalStackTrace() { 15301cb0ef41Sopenharmony_ci V8StackTraceId externalParent = m_debugger->currentExternalParent(); 15311cb0ef41Sopenharmony_ci if (externalParent.IsInvalid()) return nullptr; 15321cb0ef41Sopenharmony_ci return protocol::Runtime::StackTraceId::create() 15331cb0ef41Sopenharmony_ci .setId(stackTraceIdToString(externalParent.id)) 15341cb0ef41Sopenharmony_ci .setDebuggerId( 15351cb0ef41Sopenharmony_ci internal::V8DebuggerId(externalParent.debugger_id).toString()) 15361cb0ef41Sopenharmony_ci .build(); 15371cb0ef41Sopenharmony_ci} 15381cb0ef41Sopenharmony_ci 15391cb0ef41Sopenharmony_cibool V8DebuggerAgentImpl::isPaused() const { 15401cb0ef41Sopenharmony_ci return m_debugger->isPausedInContextGroup(m_session->contextGroupId()); 15411cb0ef41Sopenharmony_ci} 15421cb0ef41Sopenharmony_ci 15431cb0ef41Sopenharmony_cistatic String16 getScriptLanguage(const V8DebuggerScript& script) { 15441cb0ef41Sopenharmony_ci switch (script.getLanguage()) { 15451cb0ef41Sopenharmony_ci case V8DebuggerScript::Language::WebAssembly: 15461cb0ef41Sopenharmony_ci return protocol::Debugger::ScriptLanguageEnum::WebAssembly; 15471cb0ef41Sopenharmony_ci case V8DebuggerScript::Language::JavaScript: 15481cb0ef41Sopenharmony_ci return protocol::Debugger::ScriptLanguageEnum::JavaScript; 15491cb0ef41Sopenharmony_ci } 15501cb0ef41Sopenharmony_ci} 15511cb0ef41Sopenharmony_ci 15521cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY 15531cb0ef41Sopenharmony_cistatic const char* getDebugSymbolTypeName( 15541cb0ef41Sopenharmony_ci v8::debug::WasmScript::DebugSymbolsType type) { 15551cb0ef41Sopenharmony_ci switch (type) { 15561cb0ef41Sopenharmony_ci case v8::debug::WasmScript::DebugSymbolsType::None: 15571cb0ef41Sopenharmony_ci return v8_inspector::protocol::Debugger::DebugSymbols::TypeEnum::None; 15581cb0ef41Sopenharmony_ci case v8::debug::WasmScript::DebugSymbolsType::SourceMap: 15591cb0ef41Sopenharmony_ci return v8_inspector::protocol::Debugger::DebugSymbols::TypeEnum:: 15601cb0ef41Sopenharmony_ci SourceMap; 15611cb0ef41Sopenharmony_ci case v8::debug::WasmScript::DebugSymbolsType::EmbeddedDWARF: 15621cb0ef41Sopenharmony_ci return v8_inspector::protocol::Debugger::DebugSymbols::TypeEnum:: 15631cb0ef41Sopenharmony_ci EmbeddedDWARF; 15641cb0ef41Sopenharmony_ci case v8::debug::WasmScript::DebugSymbolsType::ExternalDWARF: 15651cb0ef41Sopenharmony_ci return v8_inspector::protocol::Debugger::DebugSymbols::TypeEnum:: 15661cb0ef41Sopenharmony_ci ExternalDWARF; 15671cb0ef41Sopenharmony_ci } 15681cb0ef41Sopenharmony_ci} 15691cb0ef41Sopenharmony_ci 15701cb0ef41Sopenharmony_cistatic std::unique_ptr<protocol::Debugger::DebugSymbols> getDebugSymbols( 15711cb0ef41Sopenharmony_ci const V8DebuggerScript& script) { 15721cb0ef41Sopenharmony_ci v8::debug::WasmScript::DebugSymbolsType type; 15731cb0ef41Sopenharmony_ci if (!script.getDebugSymbolsType().To(&type)) return {}; 15741cb0ef41Sopenharmony_ci 15751cb0ef41Sopenharmony_ci std::unique_ptr<protocol::Debugger::DebugSymbols> debugSymbols = 15761cb0ef41Sopenharmony_ci v8_inspector::protocol::Debugger::DebugSymbols::create() 15771cb0ef41Sopenharmony_ci .setType(getDebugSymbolTypeName(type)) 15781cb0ef41Sopenharmony_ci .build(); 15791cb0ef41Sopenharmony_ci String16 externalUrl; 15801cb0ef41Sopenharmony_ci if (script.getExternalDebugSymbolsURL().To(&externalUrl)) { 15811cb0ef41Sopenharmony_ci debugSymbols->setExternalURL(externalUrl); 15821cb0ef41Sopenharmony_ci } 15831cb0ef41Sopenharmony_ci return debugSymbols; 15841cb0ef41Sopenharmony_ci} 15851cb0ef41Sopenharmony_ci#endif // V8_ENABLE_WEBASSEMBLY 15861cb0ef41Sopenharmony_ci 15871cb0ef41Sopenharmony_civoid V8DebuggerAgentImpl::didParseSource( 15881cb0ef41Sopenharmony_ci std::unique_ptr<V8DebuggerScript> script, bool success) { 15891cb0ef41Sopenharmony_ci v8::HandleScope handles(m_isolate); 15901cb0ef41Sopenharmony_ci if (!success) { 15911cb0ef41Sopenharmony_ci String16 scriptSource = script->source(0); 15921cb0ef41Sopenharmony_ci script->setSourceURL(findSourceURL(scriptSource, false)); 15931cb0ef41Sopenharmony_ci script->setSourceMappingURL(findSourceMapURL(scriptSource, false)); 15941cb0ef41Sopenharmony_ci } 15951cb0ef41Sopenharmony_ci 15961cb0ef41Sopenharmony_ci int contextId = script->executionContextId(); 15971cb0ef41Sopenharmony_ci int contextGroupId = m_inspector->contextGroupId(contextId); 15981cb0ef41Sopenharmony_ci InspectedContext* inspected = 15991cb0ef41Sopenharmony_ci m_inspector->getContext(contextGroupId, contextId); 16001cb0ef41Sopenharmony_ci std::unique_ptr<protocol::DictionaryValue> executionContextAuxData; 16011cb0ef41Sopenharmony_ci if (inspected) { 16021cb0ef41Sopenharmony_ci // Script reused between different groups/sessions can have a stale 16031cb0ef41Sopenharmony_ci // execution context id. 16041cb0ef41Sopenharmony_ci const String16& aux = inspected->auxData(); 16051cb0ef41Sopenharmony_ci std::vector<uint8_t> cbor; 16061cb0ef41Sopenharmony_ci v8_crdtp::json::ConvertJSONToCBOR( 16071cb0ef41Sopenharmony_ci v8_crdtp::span<uint16_t>(aux.characters16(), aux.length()), &cbor); 16081cb0ef41Sopenharmony_ci executionContextAuxData = protocol::DictionaryValue::cast( 16091cb0ef41Sopenharmony_ci protocol::Value::parseBinary(cbor.data(), cbor.size())); 16101cb0ef41Sopenharmony_ci } 16111cb0ef41Sopenharmony_ci bool isLiveEdit = script->isLiveEdit(); 16121cb0ef41Sopenharmony_ci bool hasSourceURLComment = script->hasSourceURLComment(); 16131cb0ef41Sopenharmony_ci bool isModule = script->isModule(); 16141cb0ef41Sopenharmony_ci String16 scriptId = script->scriptId(); 16151cb0ef41Sopenharmony_ci String16 scriptURL = script->sourceURL(); 16161cb0ef41Sopenharmony_ci String16 embedderName = script->embedderName(); 16171cb0ef41Sopenharmony_ci String16 scriptLanguage = getScriptLanguage(*script); 16181cb0ef41Sopenharmony_ci Maybe<int> codeOffset; 16191cb0ef41Sopenharmony_ci std::unique_ptr<protocol::Debugger::DebugSymbols> debugSymbols; 16201cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY 16211cb0ef41Sopenharmony_ci if (script->getLanguage() == V8DebuggerScript::Language::WebAssembly) 16221cb0ef41Sopenharmony_ci codeOffset = script->codeOffset(); 16231cb0ef41Sopenharmony_ci debugSymbols = getDebugSymbols(*script); 16241cb0ef41Sopenharmony_ci#endif // V8_ENABLE_WEBASSEMBLY 16251cb0ef41Sopenharmony_ci 16261cb0ef41Sopenharmony_ci m_scripts[scriptId] = std::move(script); 16271cb0ef41Sopenharmony_ci // Release the strong reference to get notified when debugger is the only 16281cb0ef41Sopenharmony_ci // one that holds the script. Has to be done after script added to m_scripts. 16291cb0ef41Sopenharmony_ci m_scripts[scriptId]->MakeWeak(); 16301cb0ef41Sopenharmony_ci 16311cb0ef41Sopenharmony_ci ScriptsMap::iterator scriptIterator = m_scripts.find(scriptId); 16321cb0ef41Sopenharmony_ci DCHECK(scriptIterator != m_scripts.end()); 16331cb0ef41Sopenharmony_ci V8DebuggerScript* scriptRef = scriptIterator->second.get(); 16341cb0ef41Sopenharmony_ci // V8 could create functions for parsed scripts before reporting and asks 16351cb0ef41Sopenharmony_ci // inspector about blackboxed state, we should reset state each time when we 16361cb0ef41Sopenharmony_ci // make any change that change isFunctionBlackboxed output - adding parsed 16371cb0ef41Sopenharmony_ci // script is changing. 16381cb0ef41Sopenharmony_ci scriptRef->resetBlackboxedStateCache(); 16391cb0ef41Sopenharmony_ci 16401cb0ef41Sopenharmony_ci Maybe<String16> sourceMapURLParam = scriptRef->sourceMappingURL(); 16411cb0ef41Sopenharmony_ci Maybe<protocol::DictionaryValue> executionContextAuxDataParam( 16421cb0ef41Sopenharmony_ci std::move(executionContextAuxData)); 16431cb0ef41Sopenharmony_ci const bool* isLiveEditParam = isLiveEdit ? &isLiveEdit : nullptr; 16441cb0ef41Sopenharmony_ci const bool* hasSourceURLParam = 16451cb0ef41Sopenharmony_ci hasSourceURLComment ? &hasSourceURLComment : nullptr; 16461cb0ef41Sopenharmony_ci const bool* isModuleParam = isModule ? &isModule : nullptr; 16471cb0ef41Sopenharmony_ci std::unique_ptr<V8StackTraceImpl> stack = 16481cb0ef41Sopenharmony_ci V8StackTraceImpl::capture(m_inspector->debugger(), 1); 16491cb0ef41Sopenharmony_ci std::unique_ptr<protocol::Runtime::StackTrace> stackTrace = 16501cb0ef41Sopenharmony_ci stack && !stack->isEmpty() 16511cb0ef41Sopenharmony_ci ? stack->buildInspectorObjectImpl(m_debugger, 0) 16521cb0ef41Sopenharmony_ci : nullptr; 16531cb0ef41Sopenharmony_ci 16541cb0ef41Sopenharmony_ci if (!success) { 16551cb0ef41Sopenharmony_ci m_frontend.scriptFailedToParse( 16561cb0ef41Sopenharmony_ci scriptId, scriptURL, scriptRef->startLine(), scriptRef->startColumn(), 16571cb0ef41Sopenharmony_ci scriptRef->endLine(), scriptRef->endColumn(), contextId, 16581cb0ef41Sopenharmony_ci scriptRef->hash(), std::move(executionContextAuxDataParam), 16591cb0ef41Sopenharmony_ci std::move(sourceMapURLParam), hasSourceURLParam, isModuleParam, 16601cb0ef41Sopenharmony_ci scriptRef->length(), std::move(stackTrace), std::move(codeOffset), 16611cb0ef41Sopenharmony_ci std::move(scriptLanguage), embedderName); 16621cb0ef41Sopenharmony_ci return; 16631cb0ef41Sopenharmony_ci } 16641cb0ef41Sopenharmony_ci 16651cb0ef41Sopenharmony_ci m_frontend.scriptParsed( 16661cb0ef41Sopenharmony_ci scriptId, scriptURL, scriptRef->startLine(), scriptRef->startColumn(), 16671cb0ef41Sopenharmony_ci scriptRef->endLine(), scriptRef->endColumn(), contextId, 16681cb0ef41Sopenharmony_ci scriptRef->hash(), std::move(executionContextAuxDataParam), 16691cb0ef41Sopenharmony_ci isLiveEditParam, std::move(sourceMapURLParam), hasSourceURLParam, 16701cb0ef41Sopenharmony_ci isModuleParam, scriptRef->length(), std::move(stackTrace), 16711cb0ef41Sopenharmony_ci std::move(codeOffset), std::move(scriptLanguage), std::move(debugSymbols), 16721cb0ef41Sopenharmony_ci embedderName); 16731cb0ef41Sopenharmony_ci 16741cb0ef41Sopenharmony_ci std::vector<protocol::DictionaryValue*> potentialBreakpoints; 16751cb0ef41Sopenharmony_ci if (!scriptURL.isEmpty()) { 16761cb0ef41Sopenharmony_ci protocol::DictionaryValue* breakpointsByUrl = 16771cb0ef41Sopenharmony_ci m_state->getObject(DebuggerAgentState::breakpointsByUrl); 16781cb0ef41Sopenharmony_ci if (breakpointsByUrl) { 16791cb0ef41Sopenharmony_ci potentialBreakpoints.push_back(breakpointsByUrl->getObject(scriptURL)); 16801cb0ef41Sopenharmony_ci } 16811cb0ef41Sopenharmony_ci potentialBreakpoints.push_back( 16821cb0ef41Sopenharmony_ci m_state->getObject(DebuggerAgentState::breakpointsByRegex)); 16831cb0ef41Sopenharmony_ci } 16841cb0ef41Sopenharmony_ci protocol::DictionaryValue* breakpointsByScriptHash = 16851cb0ef41Sopenharmony_ci m_state->getObject(DebuggerAgentState::breakpointsByScriptHash); 16861cb0ef41Sopenharmony_ci if (breakpointsByScriptHash) { 16871cb0ef41Sopenharmony_ci potentialBreakpoints.push_back( 16881cb0ef41Sopenharmony_ci breakpointsByScriptHash->getObject(scriptRef->hash())); 16891cb0ef41Sopenharmony_ci } 16901cb0ef41Sopenharmony_ci protocol::DictionaryValue* breakpointHints = 16911cb0ef41Sopenharmony_ci m_state->getObject(DebuggerAgentState::breakpointHints); 16921cb0ef41Sopenharmony_ci for (auto breakpoints : potentialBreakpoints) { 16931cb0ef41Sopenharmony_ci if (!breakpoints) continue; 16941cb0ef41Sopenharmony_ci for (size_t i = 0; i < breakpoints->size(); ++i) { 16951cb0ef41Sopenharmony_ci auto breakpointWithCondition = breakpoints->at(i); 16961cb0ef41Sopenharmony_ci String16 breakpointId = breakpointWithCondition.first; 16971cb0ef41Sopenharmony_ci 16981cb0ef41Sopenharmony_ci BreakpointType type; 16991cb0ef41Sopenharmony_ci String16 selector; 17001cb0ef41Sopenharmony_ci int lineNumber = 0; 17011cb0ef41Sopenharmony_ci int columnNumber = 0; 17021cb0ef41Sopenharmony_ci parseBreakpointId(breakpointId, &type, &selector, &lineNumber, 17031cb0ef41Sopenharmony_ci &columnNumber); 17041cb0ef41Sopenharmony_ci 17051cb0ef41Sopenharmony_ci if (!matches(m_inspector, *scriptRef, type, selector)) continue; 17061cb0ef41Sopenharmony_ci String16 condition; 17071cb0ef41Sopenharmony_ci breakpointWithCondition.second->asString(&condition); 17081cb0ef41Sopenharmony_ci String16 hint; 17091cb0ef41Sopenharmony_ci bool hasHint = 17101cb0ef41Sopenharmony_ci breakpointHints && breakpointHints->getString(breakpointId, &hint); 17111cb0ef41Sopenharmony_ci if (hasHint) { 17121cb0ef41Sopenharmony_ci adjustBreakpointLocation(*scriptRef, hint, &lineNumber, &columnNumber); 17131cb0ef41Sopenharmony_ci } 17141cb0ef41Sopenharmony_ci std::unique_ptr<protocol::Debugger::Location> location = 17151cb0ef41Sopenharmony_ci setBreakpointImpl(breakpointId, scriptId, condition, lineNumber, 17161cb0ef41Sopenharmony_ci columnNumber); 17171cb0ef41Sopenharmony_ci if (location) 17181cb0ef41Sopenharmony_ci m_frontend.breakpointResolved(breakpointId, std::move(location)); 17191cb0ef41Sopenharmony_ci } 17201cb0ef41Sopenharmony_ci } 17211cb0ef41Sopenharmony_ci setScriptInstrumentationBreakpointIfNeeded(scriptRef); 17221cb0ef41Sopenharmony_ci} 17231cb0ef41Sopenharmony_ci 17241cb0ef41Sopenharmony_civoid V8DebuggerAgentImpl::setScriptInstrumentationBreakpointIfNeeded( 17251cb0ef41Sopenharmony_ci V8DebuggerScript* scriptRef) { 17261cb0ef41Sopenharmony_ci protocol::DictionaryValue* breakpoints = 17271cb0ef41Sopenharmony_ci m_state->getObject(DebuggerAgentState::instrumentationBreakpoints); 17281cb0ef41Sopenharmony_ci if (!breakpoints) return; 17291cb0ef41Sopenharmony_ci bool isBlackboxed = isFunctionBlackboxed( 17301cb0ef41Sopenharmony_ci scriptRef->scriptId(), v8::debug::Location(0, 0), 17311cb0ef41Sopenharmony_ci v8::debug::Location(scriptRef->endLine(), scriptRef->endColumn())); 17321cb0ef41Sopenharmony_ci if (isBlackboxed) return; 17331cb0ef41Sopenharmony_ci 17341cb0ef41Sopenharmony_ci String16 sourceMapURL = scriptRef->sourceMappingURL(); 17351cb0ef41Sopenharmony_ci String16 breakpointId = generateInstrumentationBreakpointId( 17361cb0ef41Sopenharmony_ci InstrumentationEnum::BeforeScriptExecution); 17371cb0ef41Sopenharmony_ci if (!breakpoints->get(breakpointId)) { 17381cb0ef41Sopenharmony_ci if (sourceMapURL.isEmpty()) return; 17391cb0ef41Sopenharmony_ci breakpointId = generateInstrumentationBreakpointId( 17401cb0ef41Sopenharmony_ci InstrumentationEnum::BeforeScriptWithSourceMapExecution); 17411cb0ef41Sopenharmony_ci if (!breakpoints->get(breakpointId)) return; 17421cb0ef41Sopenharmony_ci } 17431cb0ef41Sopenharmony_ci v8::debug::BreakpointId debuggerBreakpointId; 17441cb0ef41Sopenharmony_ci if (!scriptRef->setInstrumentationBreakpoint(&debuggerBreakpointId)) return; 17451cb0ef41Sopenharmony_ci 17461cb0ef41Sopenharmony_ci m_debuggerBreakpointIdToBreakpointId[debuggerBreakpointId] = breakpointId; 17471cb0ef41Sopenharmony_ci m_breakpointIdToDebuggerBreakpointIds[breakpointId].push_back( 17481cb0ef41Sopenharmony_ci debuggerBreakpointId); 17491cb0ef41Sopenharmony_ci} 17501cb0ef41Sopenharmony_ci 17511cb0ef41Sopenharmony_civoid V8DebuggerAgentImpl::didPauseOnInstrumentation( 17521cb0ef41Sopenharmony_ci v8::debug::BreakpointId instrumentationId) { 17531cb0ef41Sopenharmony_ci String16 breakReason = protocol::Debugger::Paused::ReasonEnum::Other; 17541cb0ef41Sopenharmony_ci std::unique_ptr<protocol::DictionaryValue> breakAuxData; 17551cb0ef41Sopenharmony_ci 17561cb0ef41Sopenharmony_ci std::unique_ptr<Array<CallFrame>> protocolCallFrames; 17571cb0ef41Sopenharmony_ci Response response = currentCallFrames(&protocolCallFrames); 17581cb0ef41Sopenharmony_ci if (!response.IsSuccess()) 17591cb0ef41Sopenharmony_ci protocolCallFrames = std::make_unique<Array<CallFrame>>(); 17601cb0ef41Sopenharmony_ci 17611cb0ef41Sopenharmony_ci if (m_debuggerBreakpointIdToBreakpointId.find(instrumentationId) != 17621cb0ef41Sopenharmony_ci m_debuggerBreakpointIdToBreakpointId.end()) { 17631cb0ef41Sopenharmony_ci DCHECK_GT(protocolCallFrames->size(), 0); 17641cb0ef41Sopenharmony_ci if (protocolCallFrames->size() > 0) { 17651cb0ef41Sopenharmony_ci breakReason = protocol::Debugger::Paused::ReasonEnum::Instrumentation; 17661cb0ef41Sopenharmony_ci const String16 scriptId = 17671cb0ef41Sopenharmony_ci protocolCallFrames->at(0)->getLocation()->getScriptId(); 17681cb0ef41Sopenharmony_ci DCHECK_NE(m_scripts.find(scriptId), m_scripts.end()); 17691cb0ef41Sopenharmony_ci const auto& script = m_scripts[scriptId]; 17701cb0ef41Sopenharmony_ci 17711cb0ef41Sopenharmony_ci breakAuxData = protocol::DictionaryValue::create(); 17721cb0ef41Sopenharmony_ci breakAuxData->setString("scriptId", script->scriptId()); 17731cb0ef41Sopenharmony_ci breakAuxData->setString("url", script->sourceURL()); 17741cb0ef41Sopenharmony_ci if (!script->sourceMappingURL().isEmpty()) { 17751cb0ef41Sopenharmony_ci breakAuxData->setString("sourceMapURL", (script->sourceMappingURL())); 17761cb0ef41Sopenharmony_ci } 17771cb0ef41Sopenharmony_ci } 17781cb0ef41Sopenharmony_ci } 17791cb0ef41Sopenharmony_ci 17801cb0ef41Sopenharmony_ci m_frontend.paused(std::move(protocolCallFrames), breakReason, 17811cb0ef41Sopenharmony_ci std::move(breakAuxData), 17821cb0ef41Sopenharmony_ci std::make_unique<Array<String16>>(), 17831cb0ef41Sopenharmony_ci currentAsyncStackTrace(), currentExternalStackTrace()); 17841cb0ef41Sopenharmony_ci} 17851cb0ef41Sopenharmony_ci 17861cb0ef41Sopenharmony_civoid V8DebuggerAgentImpl::didPause( 17871cb0ef41Sopenharmony_ci int contextId, v8::Local<v8::Value> exception, 17881cb0ef41Sopenharmony_ci const std::vector<v8::debug::BreakpointId>& hitBreakpoints, 17891cb0ef41Sopenharmony_ci v8::debug::ExceptionType exceptionType, bool isUncaught, 17901cb0ef41Sopenharmony_ci v8::debug::BreakReasons breakReasons) { 17911cb0ef41Sopenharmony_ci v8::HandleScope handles(m_isolate); 17921cb0ef41Sopenharmony_ci 17931cb0ef41Sopenharmony_ci std::vector<BreakReason> hitReasons; 17941cb0ef41Sopenharmony_ci 17951cb0ef41Sopenharmony_ci if (breakReasons.contains(v8::debug::BreakReason::kOOM)) { 17961cb0ef41Sopenharmony_ci hitReasons.push_back( 17971cb0ef41Sopenharmony_ci std::make_pair(protocol::Debugger::Paused::ReasonEnum::OOM, nullptr)); 17981cb0ef41Sopenharmony_ci } else if (breakReasons.contains(v8::debug::BreakReason::kAssert)) { 17991cb0ef41Sopenharmony_ci hitReasons.push_back(std::make_pair( 18001cb0ef41Sopenharmony_ci protocol::Debugger::Paused::ReasonEnum::Assert, nullptr)); 18011cb0ef41Sopenharmony_ci } else if (breakReasons.contains(v8::debug::BreakReason::kException)) { 18021cb0ef41Sopenharmony_ci InjectedScript* injectedScript = nullptr; 18031cb0ef41Sopenharmony_ci m_session->findInjectedScript(contextId, injectedScript); 18041cb0ef41Sopenharmony_ci if (injectedScript) { 18051cb0ef41Sopenharmony_ci String16 breakReason = 18061cb0ef41Sopenharmony_ci exceptionType == v8::debug::kPromiseRejection 18071cb0ef41Sopenharmony_ci ? protocol::Debugger::Paused::ReasonEnum::PromiseRejection 18081cb0ef41Sopenharmony_ci : protocol::Debugger::Paused::ReasonEnum::Exception; 18091cb0ef41Sopenharmony_ci std::unique_ptr<protocol::Runtime::RemoteObject> obj; 18101cb0ef41Sopenharmony_ci injectedScript->wrapObject(exception, kBacktraceObjectGroup, 18111cb0ef41Sopenharmony_ci WrapMode::kNoPreview, &obj); 18121cb0ef41Sopenharmony_ci std::unique_ptr<protocol::DictionaryValue> breakAuxData; 18131cb0ef41Sopenharmony_ci if (obj) { 18141cb0ef41Sopenharmony_ci std::vector<uint8_t> serialized; 18151cb0ef41Sopenharmony_ci obj->AppendSerialized(&serialized); 18161cb0ef41Sopenharmony_ci breakAuxData = protocol::DictionaryValue::cast( 18171cb0ef41Sopenharmony_ci protocol::Value::parseBinary(serialized.data(), serialized.size())); 18181cb0ef41Sopenharmony_ci breakAuxData->setBoolean("uncaught", isUncaught); 18191cb0ef41Sopenharmony_ci } 18201cb0ef41Sopenharmony_ci hitReasons.push_back( 18211cb0ef41Sopenharmony_ci std::make_pair(breakReason, std::move(breakAuxData))); 18221cb0ef41Sopenharmony_ci } 18231cb0ef41Sopenharmony_ci } 18241cb0ef41Sopenharmony_ci 18251cb0ef41Sopenharmony_ci auto hitBreakpointIds = std::make_unique<Array<String16>>(); 18261cb0ef41Sopenharmony_ci bool hitRegularBreakpoint = false; 18271cb0ef41Sopenharmony_ci for (const auto& id : hitBreakpoints) { 18281cb0ef41Sopenharmony_ci auto breakpointIterator = m_debuggerBreakpointIdToBreakpointId.find(id); 18291cb0ef41Sopenharmony_ci if (breakpointIterator == m_debuggerBreakpointIdToBreakpointId.end()) { 18301cb0ef41Sopenharmony_ci continue; 18311cb0ef41Sopenharmony_ci } 18321cb0ef41Sopenharmony_ci const String16& breakpointId = breakpointIterator->second; 18331cb0ef41Sopenharmony_ci hitBreakpointIds->emplace_back(breakpointId); 18341cb0ef41Sopenharmony_ci BreakpointType type; 18351cb0ef41Sopenharmony_ci parseBreakpointId(breakpointId, &type); 18361cb0ef41Sopenharmony_ci if (type == BreakpointType::kDebugCommand) { 18371cb0ef41Sopenharmony_ci hitReasons.push_back(std::make_pair( 18381cb0ef41Sopenharmony_ci protocol::Debugger::Paused::ReasonEnum::DebugCommand, nullptr)); 18391cb0ef41Sopenharmony_ci } else { 18401cb0ef41Sopenharmony_ci hitRegularBreakpoint = true; 18411cb0ef41Sopenharmony_ci } 18421cb0ef41Sopenharmony_ci } 18431cb0ef41Sopenharmony_ci 18441cb0ef41Sopenharmony_ci for (size_t i = 0; i < m_breakReason.size(); ++i) { 18451cb0ef41Sopenharmony_ci hitReasons.push_back(std::move(m_breakReason[i])); 18461cb0ef41Sopenharmony_ci } 18471cb0ef41Sopenharmony_ci clearBreakDetails(); 18481cb0ef41Sopenharmony_ci 18491cb0ef41Sopenharmony_ci // Make sure that we only include (other: nullptr) once. 18501cb0ef41Sopenharmony_ci const BreakReason otherHitReason = 18511cb0ef41Sopenharmony_ci std::make_pair(protocol::Debugger::Paused::ReasonEnum::Other, nullptr); 18521cb0ef41Sopenharmony_ci const bool otherBreakReasons = 18531cb0ef41Sopenharmony_ci hitRegularBreakpoint || hitBreakReasonEncodedAsOther(breakReasons); 18541cb0ef41Sopenharmony_ci if (otherBreakReasons && std::find(hitReasons.begin(), hitReasons.end(), 18551cb0ef41Sopenharmony_ci otherHitReason) == hitReasons.end()) { 18561cb0ef41Sopenharmony_ci hitReasons.push_back( 18571cb0ef41Sopenharmony_ci std::make_pair(protocol::Debugger::Paused::ReasonEnum::Other, nullptr)); 18581cb0ef41Sopenharmony_ci } 18591cb0ef41Sopenharmony_ci 18601cb0ef41Sopenharmony_ci // We should always know why we pause: either the pause relates to this agent 18611cb0ef41Sopenharmony_ci // (`hitReason` is non empty), or it relates to another agent (hit a 18621cb0ef41Sopenharmony_ci // breakpoint there, or a triggered pause was scheduled by other agent). 18631cb0ef41Sopenharmony_ci DCHECK(hitReasons.size() > 0 || !hitBreakpoints.empty() || 18641cb0ef41Sopenharmony_ci breakReasons.contains(v8::debug::BreakReason::kAgent)); 18651cb0ef41Sopenharmony_ci String16 breakReason = protocol::Debugger::Paused::ReasonEnum::Other; 18661cb0ef41Sopenharmony_ci std::unique_ptr<protocol::DictionaryValue> breakAuxData; 18671cb0ef41Sopenharmony_ci if (hitReasons.size() == 1) { 18681cb0ef41Sopenharmony_ci breakReason = hitReasons[0].first; 18691cb0ef41Sopenharmony_ci breakAuxData = std::move(hitReasons[0].second); 18701cb0ef41Sopenharmony_ci } else if (hitReasons.size() > 1) { 18711cb0ef41Sopenharmony_ci breakReason = protocol::Debugger::Paused::ReasonEnum::Ambiguous; 18721cb0ef41Sopenharmony_ci std::unique_ptr<protocol::ListValue> reasons = 18731cb0ef41Sopenharmony_ci protocol::ListValue::create(); 18741cb0ef41Sopenharmony_ci for (size_t i = 0; i < hitReasons.size(); ++i) { 18751cb0ef41Sopenharmony_ci std::unique_ptr<protocol::DictionaryValue> reason = 18761cb0ef41Sopenharmony_ci protocol::DictionaryValue::create(); 18771cb0ef41Sopenharmony_ci reason->setString("reason", hitReasons[i].first); 18781cb0ef41Sopenharmony_ci if (hitReasons[i].second) 18791cb0ef41Sopenharmony_ci reason->setObject("auxData", std::move(hitReasons[i].second)); 18801cb0ef41Sopenharmony_ci reasons->pushValue(std::move(reason)); 18811cb0ef41Sopenharmony_ci } 18821cb0ef41Sopenharmony_ci breakAuxData = protocol::DictionaryValue::create(); 18831cb0ef41Sopenharmony_ci breakAuxData->setArray("reasons", std::move(reasons)); 18841cb0ef41Sopenharmony_ci } 18851cb0ef41Sopenharmony_ci 18861cb0ef41Sopenharmony_ci std::unique_ptr<Array<CallFrame>> protocolCallFrames; 18871cb0ef41Sopenharmony_ci Response response = currentCallFrames(&protocolCallFrames); 18881cb0ef41Sopenharmony_ci if (!response.IsSuccess()) 18891cb0ef41Sopenharmony_ci protocolCallFrames = std::make_unique<Array<CallFrame>>(); 18901cb0ef41Sopenharmony_ci 18911cb0ef41Sopenharmony_ci m_frontend.paused(std::move(protocolCallFrames), breakReason, 18921cb0ef41Sopenharmony_ci std::move(breakAuxData), std::move(hitBreakpointIds), 18931cb0ef41Sopenharmony_ci currentAsyncStackTrace(), currentExternalStackTrace()); 18941cb0ef41Sopenharmony_ci} 18951cb0ef41Sopenharmony_ci 18961cb0ef41Sopenharmony_civoid V8DebuggerAgentImpl::didContinue() { 18971cb0ef41Sopenharmony_ci m_frontend.resumed(); 18981cb0ef41Sopenharmony_ci m_frontend.flush(); 18991cb0ef41Sopenharmony_ci} 19001cb0ef41Sopenharmony_ci 19011cb0ef41Sopenharmony_civoid V8DebuggerAgentImpl::breakProgram( 19021cb0ef41Sopenharmony_ci const String16& breakReason, 19031cb0ef41Sopenharmony_ci std::unique_ptr<protocol::DictionaryValue> data) { 19041cb0ef41Sopenharmony_ci if (!enabled() || m_skipAllPauses || !m_debugger->canBreakProgram()) return; 19051cb0ef41Sopenharmony_ci std::vector<BreakReason> currentScheduledReason; 19061cb0ef41Sopenharmony_ci currentScheduledReason.swap(m_breakReason); 19071cb0ef41Sopenharmony_ci pushBreakDetails(breakReason, std::move(data)); 19081cb0ef41Sopenharmony_ci 19091cb0ef41Sopenharmony_ci int contextGroupId = m_session->contextGroupId(); 19101cb0ef41Sopenharmony_ci int sessionId = m_session->sessionId(); 19111cb0ef41Sopenharmony_ci V8InspectorImpl* inspector = m_inspector; 19121cb0ef41Sopenharmony_ci m_debugger->breakProgram(contextGroupId); 19131cb0ef41Sopenharmony_ci // Check that session and |this| are still around. 19141cb0ef41Sopenharmony_ci if (!inspector->sessionById(contextGroupId, sessionId)) return; 19151cb0ef41Sopenharmony_ci if (!enabled()) return; 19161cb0ef41Sopenharmony_ci 19171cb0ef41Sopenharmony_ci popBreakDetails(); 19181cb0ef41Sopenharmony_ci m_breakReason.swap(currentScheduledReason); 19191cb0ef41Sopenharmony_ci if (!m_breakReason.empty()) { 19201cb0ef41Sopenharmony_ci m_debugger->setPauseOnNextCall(true, m_session->contextGroupId()); 19211cb0ef41Sopenharmony_ci } 19221cb0ef41Sopenharmony_ci} 19231cb0ef41Sopenharmony_ci 19241cb0ef41Sopenharmony_civoid V8DebuggerAgentImpl::setBreakpointFor(v8::Local<v8::Function> function, 19251cb0ef41Sopenharmony_ci v8::Local<v8::String> condition, 19261cb0ef41Sopenharmony_ci BreakpointSource source) { 19271cb0ef41Sopenharmony_ci String16 breakpointId = generateBreakpointId( 19281cb0ef41Sopenharmony_ci source == DebugCommandBreakpointSource ? BreakpointType::kDebugCommand 19291cb0ef41Sopenharmony_ci : BreakpointType::kMonitorCommand, 19301cb0ef41Sopenharmony_ci function); 19311cb0ef41Sopenharmony_ci if (m_breakpointIdToDebuggerBreakpointIds.find(breakpointId) != 19321cb0ef41Sopenharmony_ci m_breakpointIdToDebuggerBreakpointIds.end()) { 19331cb0ef41Sopenharmony_ci return; 19341cb0ef41Sopenharmony_ci } 19351cb0ef41Sopenharmony_ci setBreakpointImpl(breakpointId, function, condition); 19361cb0ef41Sopenharmony_ci} 19371cb0ef41Sopenharmony_ci 19381cb0ef41Sopenharmony_civoid V8DebuggerAgentImpl::removeBreakpointFor(v8::Local<v8::Function> function, 19391cb0ef41Sopenharmony_ci BreakpointSource source) { 19401cb0ef41Sopenharmony_ci String16 breakpointId = generateBreakpointId( 19411cb0ef41Sopenharmony_ci source == DebugCommandBreakpointSource ? BreakpointType::kDebugCommand 19421cb0ef41Sopenharmony_ci : BreakpointType::kMonitorCommand, 19431cb0ef41Sopenharmony_ci function); 19441cb0ef41Sopenharmony_ci std::vector<V8DebuggerScript*> scripts; 19451cb0ef41Sopenharmony_ci removeBreakpointImpl(breakpointId, scripts); 19461cb0ef41Sopenharmony_ci} 19471cb0ef41Sopenharmony_ci 19481cb0ef41Sopenharmony_civoid V8DebuggerAgentImpl::reset() { 19491cb0ef41Sopenharmony_ci if (!enabled()) return; 19501cb0ef41Sopenharmony_ci m_blackboxedPositions.clear(); 19511cb0ef41Sopenharmony_ci resetBlackboxedStateCache(); 19521cb0ef41Sopenharmony_ci m_skipList.clear(); 19531cb0ef41Sopenharmony_ci m_scripts.clear(); 19541cb0ef41Sopenharmony_ci m_cachedScripts.clear(); 19551cb0ef41Sopenharmony_ci m_cachedScriptSize = 0; 19561cb0ef41Sopenharmony_ci} 19571cb0ef41Sopenharmony_ci 19581cb0ef41Sopenharmony_civoid V8DebuggerAgentImpl::ScriptCollected(const V8DebuggerScript* script) { 19591cb0ef41Sopenharmony_ci DCHECK_NE(m_scripts.find(script->scriptId()), m_scripts.end()); 19601cb0ef41Sopenharmony_ci std::vector<uint8_t> bytecode; 19611cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY 19621cb0ef41Sopenharmony_ci v8::MemorySpan<const uint8_t> span; 19631cb0ef41Sopenharmony_ci if (script->wasmBytecode().To(&span)) { 19641cb0ef41Sopenharmony_ci bytecode.reserve(span.size()); 19651cb0ef41Sopenharmony_ci bytecode.insert(bytecode.begin(), span.data(), span.data() + span.size()); 19661cb0ef41Sopenharmony_ci } 19671cb0ef41Sopenharmony_ci#endif 19681cb0ef41Sopenharmony_ci CachedScript cachedScript{script->scriptId(), script->source(0), 19691cb0ef41Sopenharmony_ci std::move(bytecode)}; 19701cb0ef41Sopenharmony_ci m_cachedScriptSize += cachedScript.size(); 19711cb0ef41Sopenharmony_ci m_cachedScripts.push_back(std::move(cachedScript)); 19721cb0ef41Sopenharmony_ci m_scripts.erase(script->scriptId()); 19731cb0ef41Sopenharmony_ci 19741cb0ef41Sopenharmony_ci while (m_cachedScriptSize > m_maxScriptCacheSize) { 19751cb0ef41Sopenharmony_ci const CachedScript& cachedScript = m_cachedScripts.front(); 19761cb0ef41Sopenharmony_ci DCHECK_GE(m_cachedScriptSize, cachedScript.size()); 19771cb0ef41Sopenharmony_ci m_cachedScriptSize -= cachedScript.size(); 19781cb0ef41Sopenharmony_ci m_cachedScripts.pop_front(); 19791cb0ef41Sopenharmony_ci } 19801cb0ef41Sopenharmony_ci} 19811cb0ef41Sopenharmony_ci 19821cb0ef41Sopenharmony_ciResponse V8DebuggerAgentImpl::processSkipList( 19831cb0ef41Sopenharmony_ci protocol::Array<protocol::Debugger::LocationRange>* skipList) { 19841cb0ef41Sopenharmony_ci std::unordered_map<String16, std::vector<std::pair<int, int>>> skipListInit; 19851cb0ef41Sopenharmony_ci for (std::unique_ptr<protocol::Debugger::LocationRange>& range : *skipList) { 19861cb0ef41Sopenharmony_ci protocol::Debugger::ScriptPosition* start = range->getStart(); 19871cb0ef41Sopenharmony_ci protocol::Debugger::ScriptPosition* end = range->getEnd(); 19881cb0ef41Sopenharmony_ci String16 scriptId = range->getScriptId(); 19891cb0ef41Sopenharmony_ci 19901cb0ef41Sopenharmony_ci auto it = m_scripts.find(scriptId); 19911cb0ef41Sopenharmony_ci if (it == m_scripts.end()) 19921cb0ef41Sopenharmony_ci return Response::ServerError("No script with passed id."); 19931cb0ef41Sopenharmony_ci 19941cb0ef41Sopenharmony_ci Response res = isValidPosition(start); 19951cb0ef41Sopenharmony_ci if (res.IsError()) return res; 19961cb0ef41Sopenharmony_ci 19971cb0ef41Sopenharmony_ci res = isValidPosition(end); 19981cb0ef41Sopenharmony_ci if (res.IsError()) return res; 19991cb0ef41Sopenharmony_ci 20001cb0ef41Sopenharmony_ci skipListInit[scriptId].emplace_back(start->getLineNumber(), 20011cb0ef41Sopenharmony_ci start->getColumnNumber()); 20021cb0ef41Sopenharmony_ci skipListInit[scriptId].emplace_back(end->getLineNumber(), 20031cb0ef41Sopenharmony_ci end->getColumnNumber()); 20041cb0ef41Sopenharmony_ci } 20051cb0ef41Sopenharmony_ci 20061cb0ef41Sopenharmony_ci // Verify that the skipList is sorted, and that all ranges 20071cb0ef41Sopenharmony_ci // are properly defined (start comes before end). 20081cb0ef41Sopenharmony_ci for (auto skipListPair : skipListInit) { 20091cb0ef41Sopenharmony_ci Response res = isValidRangeOfPositions(skipListPair.second); 20101cb0ef41Sopenharmony_ci if (res.IsError()) return res; 20111cb0ef41Sopenharmony_ci } 20121cb0ef41Sopenharmony_ci 20131cb0ef41Sopenharmony_ci m_skipList = std::move(skipListInit); 20141cb0ef41Sopenharmony_ci return Response::Success(); 20151cb0ef41Sopenharmony_ci} 20161cb0ef41Sopenharmony_ci} // namespace v8_inspector 2017