summaryrefslogtreecommitdiff
path: root/deps/v8/src/inspector
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/inspector')
-rw-r--r--deps/v8/src/inspector/DEPS1
-rw-r--r--deps/v8/src/inspector/debugger-script.js7
-rw-r--r--deps/v8/src/inspector/debugger_script_externs.js3
-rw-r--r--deps/v8/src/inspector/inspected-context.cc28
-rw-r--r--deps/v8/src/inspector/inspector.gyp32
-rw-r--r--deps/v8/src/inspector/js_protocol.json11
-rw-r--r--deps/v8/src/inspector/string-util.cc12
-rw-r--r--deps/v8/src/inspector/string-util.h1
-rw-r--r--deps/v8/src/inspector/test-interface.cc8
-rw-r--r--deps/v8/src/inspector/test-interface.h1
-rw-r--r--deps/v8/src/inspector/v8-console.cc183
-rw-r--r--deps/v8/src/inspector/v8-console.h57
-rw-r--r--deps/v8/src/inspector/v8-debugger-agent-impl.cc62
-rw-r--r--deps/v8/src/inspector/v8-debugger-agent-impl.h6
-rw-r--r--deps/v8/src/inspector/v8-debugger-script.cc6
-rw-r--r--deps/v8/src/inspector/v8-debugger.cc298
-rw-r--r--deps/v8/src/inspector/v8-debugger.h58
-rw-r--r--deps/v8/src/inspector/v8-function-call.cc2
-rw-r--r--deps/v8/src/inspector/v8-inspector-impl.cc8
-rw-r--r--deps/v8/src/inspector/v8-regex.cc1
-rw-r--r--deps/v8/src/inspector/v8-stack-trace-impl.cc473
-rw-r--r--deps/v8/src/inspector/v8-stack-trace-impl.h162
22 files changed, 802 insertions, 618 deletions
diff --git a/deps/v8/src/inspector/DEPS b/deps/v8/src/inspector/DEPS
index 2d77fb7aa7..b69626cdb8 100644
--- a/deps/v8/src/inspector/DEPS
+++ b/deps/v8/src/inspector/DEPS
@@ -6,6 +6,7 @@ include_rules = [
"+src/base/logging.h",
"+src/base/platform/platform.h",
"+src/conversions.h",
+ "+src/unicode-cache.h",
"+src/inspector",
"+src/tracing",
"+src/debug/debug-interface.h",
diff --git a/deps/v8/src/inspector/debugger-script.js b/deps/v8/src/inspector/debugger-script.js
index d9cb12a09a..89f0d75903 100644
--- a/deps/v8/src/inspector/debugger-script.js
+++ b/deps/v8/src/inspector/debugger-script.js
@@ -402,10 +402,9 @@ DebuggerScript._frameMirrorToJSCallFrame = function(frameMirror)
*/
function contextId()
{
- var mirror = ensureFuncMirror();
- var context = mirror.context();
- if (context && context.data())
- return Number(context.data());
+ var context =
+ ensureFuncMirror().context() || ensureScriptMirror().context();
+ if (context && context.data()) return Number(context.data());
return 0;
}
diff --git a/deps/v8/src/inspector/debugger_script_externs.js b/deps/v8/src/inspector/debugger_script_externs.js
index 6f36fb9c41..656bada862 100644
--- a/deps/v8/src/inspector/debugger_script_externs.js
+++ b/deps/v8/src/inspector/debugger_script_externs.js
@@ -355,6 +355,9 @@ ScriptMirror.prototype.value = function() {}
/** @return {number} */
ScriptMirror.prototype.id = function() {}
+/** @return {ContextMirror} */
+ScriptMirror.prototype.context = function() {}
+
/**
* @param {number} position
* @param {boolean=} includeResourceOffset
diff --git a/deps/v8/src/inspector/inspected-context.cc b/deps/v8/src/inspector/inspected-context.cc
index 0509683789..27766f200a 100644
--- a/deps/v8/src/inspector/inspected-context.cc
+++ b/deps/v8/src/inspector/inspected-context.cc
@@ -4,6 +4,7 @@
#include "src/inspector/inspected-context.h"
+#include "src/debug/debug-interface.h"
#include "src/inspector/injected-script.h"
#include "src/inspector/string-util.h"
#include "src/inspector/v8-console.h"
@@ -24,20 +25,16 @@ InspectedContext::InspectedContext(V8InspectorImpl* inspector,
m_humanReadableName(toString16(info.humanReadableName)),
m_auxData(toString16(info.auxData)),
m_reported(false) {
- v8::Isolate* isolate = m_inspector->isolate();
- info.context->SetEmbedderData(static_cast<int>(v8::Context::kDebugIdIndex),
- v8::Int32::New(isolate, contextId));
+ v8::debug::SetContextId(info.context, contextId);
+ if (!info.hasMemoryOnConsole) return;
+ v8::Context::Scope contextScope(info.context);
v8::Local<v8::Object> global = info.context->Global();
- v8::Local<v8::Object> console =
- m_inspector->console()->createConsole(info.context);
- if (info.hasMemoryOnConsole) {
- m_inspector->console()->installMemoryGetter(info.context, console);
- }
- if (!global
- ->Set(info.context, toV8StringInternalized(isolate, "console"),
- console)
- .FromMaybe(false)) {
- return;
+ v8::Local<v8::Value> console;
+ if (global->Get(info.context, toV8String(m_inspector->isolate(), "console"))
+ .ToLocal(&console) &&
+ console->IsObject()) {
+ m_inspector->console()->installMemoryGetter(
+ info.context, v8::Local<v8::Object>::Cast(console));
}
}
@@ -46,10 +43,7 @@ InspectedContext::~InspectedContext() {
// static
int InspectedContext::contextId(v8::Local<v8::Context> context) {
- v8::Local<v8::Value> data =
- context->GetEmbedderData(static_cast<int>(v8::Context::kDebugIdIndex));
- if (data.IsEmpty() || !data->IsInt32()) return 0;
- return static_cast<int>(data.As<v8::Int32>()->Value());
+ return v8::debug::GetContextId(context);
}
v8::Local<v8::Context> InspectedContext::context() const {
diff --git a/deps/v8/src/inspector/inspector.gyp b/deps/v8/src/inspector/inspector.gyp
index 91507bd579..bedab694a8 100644
--- a/deps/v8/src/inspector/inspector.gyp
+++ b/deps/v8/src/inspector/inspector.gyp
@@ -13,13 +13,7 @@
'targets': [
{ 'target_name': 'inspector_injected_script',
'type': 'none',
- 'conditions': [
- ['want_separate_host_toolset==1', {
- 'toolsets': ['host', 'target'],
- }, {
- 'toolsets': ['target'],
- }]
- ],
+ 'toolsets': ['target'],
'actions': [
{
'action_name': 'convert_js_to_cpp_char_array',
@@ -44,13 +38,7 @@
},
{ 'target_name': 'inspector_debugger_script',
'type': 'none',
- 'conditions': [
- ['want_separate_host_toolset==1', {
- 'toolsets': ['host', 'target'],
- }, {
- 'toolsets': ['target'],
- }]
- ],
+ 'toolsets': ['target'],
'actions': [
{
'action_name': 'convert_js_to_cpp_char_array',
@@ -75,13 +63,7 @@
},
{ 'target_name': 'protocol_compatibility',
'type': 'none',
- 'conditions': [
- ['want_separate_host_toolset==1', {
- 'toolsets': ['host', 'target'],
- }, {
- 'toolsets': ['target'],
- }]
- ],
+ 'toolsets': ['target'],
'actions': [
{
'action_name': 'protocol_compatibility',
@@ -104,13 +86,7 @@
{ 'target_name': 'protocol_generated_sources',
'type': 'none',
'dependencies': [ 'protocol_compatibility' ],
- 'conditions': [
- ['want_separate_host_toolset==1', {
- 'toolsets': ['host', 'target'],
- }, {
- 'toolsets': ['target'],
- }]
- ],
+ 'toolsets': ['target'],
'actions': [
{
'action_name': 'protocol_generated_sources',
diff --git a/deps/v8/src/inspector/js_protocol.json b/deps/v8/src/inspector/js_protocol.json
index 7384835fdc..62545cd80d 100644
--- a/deps/v8/src/inspector/js_protocol.json
+++ b/deps/v8/src/inspector/js_protocol.json
@@ -349,7 +349,7 @@
{
"name": "executionContextCreated",
"parameters": [
- { "name": "context", "$ref": "ExecutionContextDescription", "description": "A newly created execution contex." }
+ { "name": "context", "$ref": "ExecutionContextDescription", "description": "A newly created execution context." }
],
"description": "Issued when new execution context is created."
},
@@ -545,7 +545,7 @@
"name": "getPossibleBreakpoints",
"parameters": [
{ "name": "start", "$ref": "Location", "description": "Start of range to search possible breakpoint locations in." },
- { "name": "end", "$ref": "Location", "optional": true, "description": "End of range to search possible breakpoint locations in (excluding). When not specifed, end of scripts is used as end of range." },
+ { "name": "end", "$ref": "Location", "optional": true, "description": "End of range to search possible breakpoint locations in (excluding). When not specified, end of scripts is used as end of range." },
{ "name": "restrictToFunction", "type": "boolean", "optional": true, "description": "Only consider locations which are in the same (non-nested) function as start." }
],
"returns": [
@@ -557,7 +557,8 @@
{
"name": "continueToLocation",
"parameters": [
- { "name": "location", "$ref": "Location", "description": "Location to continue to." }
+ { "name": "location", "$ref": "Location", "description": "Location to continue to." },
+ { "name": "targetCallFrames", "type": "string", "enum": ["any", "current"], "optional": true, "experimental": true }
],
"description": "Continues execution until specific location is reached."
},
@@ -938,7 +939,7 @@
{ "name": "location", "$ref": "Debugger.Location", "description": "Location of console.profile()." },
{ "name": "title", "type": "string", "optional": true, "description": "Profile title passed as an argument to console.profile()." }
],
- "description": "Sent when new profile recodring is started using console.profile() call."
+ "description": "Sent when new profile recording is started using console.profile() call."
},
{
"name": "consoleProfileFinished",
@@ -1067,7 +1068,7 @@
},
{
"name": "lastSeenObjectId",
- "description": "If heap objects tracking has been started then backend regulary sends a current value for last seen object id and corresponding timestamp. If the were changes in the heap since last event then one or more heapStatsUpdate events will be sent before a new lastSeenObjectId event.",
+ "description": "If heap objects tracking has been started then backend regularly sends a current value for last seen object id and corresponding timestamp. If the were changes in the heap since last event then one or more heapStatsUpdate events will be sent before a new lastSeenObjectId event.",
"parameters": [
{ "name": "lastSeenObjectId", "type": "integer" },
{ "name": "timestamp", "type": "number" }
diff --git a/deps/v8/src/inspector/string-util.cc b/deps/v8/src/inspector/string-util.cc
index 31b2db572d..95d4247d14 100644
--- a/deps/v8/src/inspector/string-util.cc
+++ b/deps/v8/src/inspector/string-util.cc
@@ -4,7 +4,9 @@
#include "src/inspector/string-util.h"
+#include "src/conversions.h"
#include "src/inspector/protocol/Protocol.h"
+#include "src/unicode-cache.h"
namespace v8_inspector {
@@ -92,6 +94,16 @@ bool stringViewStartsWith(const StringView& string, const char* prefix) {
namespace protocol {
+// static
+double StringUtil::toDouble(const char* s, size_t len, bool* isOk) {
+ v8::internal::UnicodeCache unicode_cache;
+ int flags = v8::internal::ALLOW_HEX | v8::internal::ALLOW_OCTAL |
+ v8::internal::ALLOW_BINARY;
+ double result = StringToDouble(&unicode_cache, s, flags);
+ *isOk = !std::isnan(result);
+ return result;
+}
+
std::unique_ptr<protocol::Value> StringUtil::parseJSON(
const StringView& string) {
if (!string.length()) return nullptr;
diff --git a/deps/v8/src/inspector/string-util.h b/deps/v8/src/inspector/string-util.h
index 6f0e3d5ff5..134ff425e1 100644
--- a/deps/v8/src/inspector/string-util.h
+++ b/deps/v8/src/inspector/string-util.h
@@ -32,6 +32,7 @@ class StringUtil {
return String::fromInteger(number);
}
static String fromDouble(double number) { return String::fromDouble(number); }
+ static double toDouble(const char* s, size_t len, bool* isOk);
static size_t find(const String& s, const char* needle) {
return s.find(needle);
}
diff --git a/deps/v8/src/inspector/test-interface.cc b/deps/v8/src/inspector/test-interface.cc
index ead1dc3b81..6167f8be27 100644
--- a/deps/v8/src/inspector/test-interface.cc
+++ b/deps/v8/src/inspector/test-interface.cc
@@ -15,4 +15,10 @@ void SetMaxAsyncTaskStacksForTest(V8Inspector* inspector, int limit) {
->setMaxAsyncTaskStacksForTest(limit);
}
-} // v8_inspector
+void DumpAsyncTaskStacksStateForTest(V8Inspector* inspector) {
+ static_cast<V8InspectorImpl*>(inspector)
+ ->debugger()
+ ->dumpAsyncTaskStacksStateForTest();
+}
+
+} // namespace v8_inspector
diff --git a/deps/v8/src/inspector/test-interface.h b/deps/v8/src/inspector/test-interface.h
index 98bedc2786..70fbca186f 100644
--- a/deps/v8/src/inspector/test-interface.h
+++ b/deps/v8/src/inspector/test-interface.h
@@ -12,6 +12,7 @@ namespace v8_inspector {
class V8Inspector;
V8_EXPORT void SetMaxAsyncTaskStacksForTest(V8Inspector* inspector, int limit);
+V8_EXPORT void DumpAsyncTaskStacksStateForTest(V8Inspector* inspector);
} // v8_inspector
diff --git a/deps/v8/src/inspector/v8-console.cc b/deps/v8/src/inspector/v8-console.cc
index 69e58dfabd..0d3c03a4da 100644
--- a/deps/v8/src/inspector/v8-console.cc
+++ b/deps/v8/src/inspector/v8-console.cc
@@ -25,11 +25,11 @@ namespace {
class ConsoleHelper {
public:
- explicit ConsoleHelper(const v8::FunctionCallbackInfo<v8::Value>& info,
- V8InspectorImpl* inspector)
+ ConsoleHelper(const v8::debug::ConsoleCallArguments& info,
+ V8InspectorImpl* inspector)
: m_info(info),
- m_isolate(info.GetIsolate()),
- m_context(info.GetIsolate()->GetCurrentContext()),
+ m_isolate(inspector->isolate()),
+ m_context(m_isolate->GetCurrentContext()),
m_inspector(inspector),
m_contextId(InspectedContext::contextId(m_context)),
m_groupId(m_inspector->contextGroupId(m_contextId)) {}
@@ -145,7 +145,7 @@ class ConsoleHelper {
}
private:
- const v8::FunctionCallbackInfo<v8::Value>& m_info;
+ const v8::debug::ConsoleCallArguments& m_info;
v8::Isolate* m_isolate;
v8::Local<v8::Context> m_context;
V8InspectorImpl* m_inspector = nullptr;
@@ -190,66 +190,63 @@ void createBoundFunctionProperty(v8::Local<v8::Context> context,
V8Console::V8Console(V8InspectorImpl* inspector) : m_inspector(inspector) {}
-void V8Console::debugCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
+void V8Console::Debug(const v8::debug::ConsoleCallArguments& info) {
ConsoleHelper(info, m_inspector).reportCall(ConsoleAPIType::kDebug);
}
-void V8Console::errorCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
+void V8Console::Error(const v8::debug::ConsoleCallArguments& info) {
ConsoleHelper(info, m_inspector).reportCall(ConsoleAPIType::kError);
}
-void V8Console::infoCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
+void V8Console::Info(const v8::debug::ConsoleCallArguments& info) {
ConsoleHelper(info, m_inspector).reportCall(ConsoleAPIType::kInfo);
}
-void V8Console::logCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
+void V8Console::Log(const v8::debug::ConsoleCallArguments& info) {
ConsoleHelper(info, m_inspector).reportCall(ConsoleAPIType::kLog);
}
-void V8Console::warnCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
+void V8Console::Warn(const v8::debug::ConsoleCallArguments& info) {
ConsoleHelper(info, m_inspector).reportCall(ConsoleAPIType::kWarning);
}
-void V8Console::dirCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
+void V8Console::Dir(const v8::debug::ConsoleCallArguments& info) {
ConsoleHelper(info, m_inspector).reportCall(ConsoleAPIType::kDir);
}
-void V8Console::dirxmlCallback(
- const v8::FunctionCallbackInfo<v8::Value>& info) {
+void V8Console::DirXml(const v8::debug::ConsoleCallArguments& info) {
ConsoleHelper(info, m_inspector).reportCall(ConsoleAPIType::kDirXML);
}
-void V8Console::tableCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
+void V8Console::Table(const v8::debug::ConsoleCallArguments& info) {
ConsoleHelper(info, m_inspector).reportCall(ConsoleAPIType::kTable);
}
-void V8Console::traceCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
+void V8Console::Trace(const v8::debug::ConsoleCallArguments& info) {
ConsoleHelper(info, m_inspector)
.reportCallWithDefaultArgument(ConsoleAPIType::kTrace,
String16("console.trace"));
}
-void V8Console::groupCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
+void V8Console::Group(const v8::debug::ConsoleCallArguments& info) {
ConsoleHelper(info, m_inspector)
.reportCallWithDefaultArgument(ConsoleAPIType::kStartGroup,
String16("console.group"));
}
-void V8Console::groupCollapsedCallback(
- const v8::FunctionCallbackInfo<v8::Value>& info) {
+void V8Console::GroupCollapsed(const v8::debug::ConsoleCallArguments& info) {
ConsoleHelper(info, m_inspector)
.reportCallWithDefaultArgument(ConsoleAPIType::kStartGroupCollapsed,
String16("console.groupCollapsed"));
}
-void V8Console::groupEndCallback(
- const v8::FunctionCallbackInfo<v8::Value>& info) {
+void V8Console::GroupEnd(const v8::debug::ConsoleCallArguments& info) {
ConsoleHelper(info, m_inspector)
.reportCallWithDefaultArgument(ConsoleAPIType::kEndGroup,
String16("console.groupEnd"));
}
-void V8Console::clearCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
+void V8Console::Clear(const v8::debug::ConsoleCallArguments& info) {
ConsoleHelper helper(info, m_inspector);
if (!helper.groupId()) return;
m_inspector->client()->consoleClear(helper.groupId());
@@ -257,13 +254,13 @@ void V8Console::clearCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
String16("console.clear"));
}
-void V8Console::countCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
+void V8Console::Count(const v8::debug::ConsoleCallArguments& info) {
ConsoleHelper helper(info, m_inspector);
String16 title = helper.firstArgToString(String16());
String16 identifier;
if (title.isEmpty()) {
std::unique_ptr<V8StackTraceImpl> stackTrace =
- V8StackTraceImpl::capture(m_inspector->debugger(), 0, 1);
+ V8StackTraceImpl::capture(m_inspector->debugger(), helper.groupId(), 1);
if (stackTrace && !stackTrace->isEmpty()) {
identifier = toString16(stackTrace->topSourceURL()) + ":" +
String16::fromInteger(stackTrace->topLineNumber());
@@ -280,16 +277,15 @@ void V8Console::countCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
title.isEmpty() ? countString : (title + ": " + countString));
}
-void V8Console::assertCallback(
- const v8::FunctionCallbackInfo<v8::Value>& info) {
+void V8Console::Assert(const v8::debug::ConsoleCallArguments& info) {
ConsoleHelper helper(info, m_inspector);
- if (helper.firstArgToBoolean(false)) return;
+ DCHECK(!helper.firstArgToBoolean(false));
std::vector<v8::Local<v8::Value>> arguments;
for (int i = 1; i < info.Length(); ++i) arguments.push_back(info[i]);
if (info.Length() < 2)
arguments.push_back(
- toV8String(info.GetIsolate(), String16("console.assert")));
+ toV8String(m_inspector->isolate(), String16("console.assert")));
helper.reportCall(ConsoleAPIType::kAssert, arguments);
if (V8DebuggerAgentImpl* debuggerAgent = helper.debuggerAgent())
@@ -297,31 +293,28 @@ void V8Console::assertCallback(
protocol::Debugger::Paused::ReasonEnum::Assert, nullptr);
}
-void V8Console::markTimelineCallback(
- const v8::FunctionCallbackInfo<v8::Value>& info) {
+void V8Console::MarkTimeline(const v8::debug::ConsoleCallArguments& info) {
ConsoleHelper(info, m_inspector)
.reportDeprecatedCall("V8Console#markTimelineDeprecated",
"'console.markTimeline' is "
"deprecated. Please use "
"'console.timeStamp' instead.");
- timeStampCallback(info);
+ TimeStamp(info);
}
-void V8Console::profileCallback(
- const v8::FunctionCallbackInfo<v8::Value>& info) {
+void V8Console::Profile(const v8::debug::ConsoleCallArguments& info) {
ConsoleHelper helper(info, m_inspector);
if (V8ProfilerAgentImpl* profilerAgent = helper.profilerAgent())
profilerAgent->consoleProfile(helper.firstArgToString(String16()));
}
-void V8Console::profileEndCallback(
- const v8::FunctionCallbackInfo<v8::Value>& info) {
+void V8Console::ProfileEnd(const v8::debug::ConsoleCallArguments& info) {
ConsoleHelper helper(info, m_inspector);
if (V8ProfilerAgentImpl* profilerAgent = helper.profilerAgent())
profilerAgent->consoleProfileEnd(helper.firstArgToString(String16()));
}
-static void timeFunction(const v8::FunctionCallbackInfo<v8::Value>& info,
+static void timeFunction(const v8::debug::ConsoleCallArguments& info,
bool timelinePrefix, V8InspectorImpl* inspector) {
ConsoleHelper helper(info, inspector);
String16 protocolTitle = helper.firstArgToString("default");
@@ -330,7 +323,7 @@ static void timeFunction(const v8::FunctionCallbackInfo<v8::Value>& info,
helper.consoleMessageStorage()->time(helper.contextId(), protocolTitle);
}
-static void timeEndFunction(const v8::FunctionCallbackInfo<v8::Value>& info,
+static void timeEndFunction(const v8::debug::ConsoleCallArguments& info,
bool timelinePrefix, V8InspectorImpl* inspector) {
ConsoleHelper helper(info, inspector);
String16 protocolTitle = helper.firstArgToString("default");
@@ -343,8 +336,7 @@ static void timeEndFunction(const v8::FunctionCallbackInfo<v8::Value>& info,
helper.reportCallWithArgument(ConsoleAPIType::kTimeEnd, message);
}
-void V8Console::timelineCallback(
- const v8::FunctionCallbackInfo<v8::Value>& info) {
+void V8Console::Timeline(const v8::debug::ConsoleCallArguments& info) {
ConsoleHelper(info, m_inspector)
.reportDeprecatedCall("V8Console#timeline",
"'console.timeline' is deprecated. Please use "
@@ -352,8 +344,7 @@ void V8Console::timelineCallback(
timeFunction(info, true, m_inspector);
}
-void V8Console::timelineEndCallback(
- const v8::FunctionCallbackInfo<v8::Value>& info) {
+void V8Console::TimelineEnd(const v8::debug::ConsoleCallArguments& info) {
ConsoleHelper(info, m_inspector)
.reportDeprecatedCall("V8Console#timelineEnd",
"'console.timelineEnd' is "
@@ -362,17 +353,15 @@ void V8Console::timelineEndCallback(
timeEndFunction(info, true, m_inspector);
}
-void V8Console::timeCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
+void V8Console::Time(const v8::debug::ConsoleCallArguments& info) {
timeFunction(info, false, m_inspector);
}
-void V8Console::timeEndCallback(
- const v8::FunctionCallbackInfo<v8::Value>& info) {
+void V8Console::TimeEnd(const v8::debug::ConsoleCallArguments& info) {
timeEndFunction(info, false, m_inspector);
}
-void V8Console::timeStampCallback(
- const v8::FunctionCallbackInfo<v8::Value>& info) {
+void V8Console::TimeStamp(const v8::debug::ConsoleCallArguments& info) {
ConsoleHelper helper(info, m_inspector);
String16 title = helper.firstArgToString(String16());
m_inspector->client()->consoleTimeStamp(toStringView(title));
@@ -400,7 +389,8 @@ void V8Console::keysCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
v8::Isolate* isolate = info.GetIsolate();
info.GetReturnValue().Set(v8::Array::New(isolate));
- ConsoleHelper helper(info, m_inspector);
+ v8::debug::ConsoleCallArguments args(info);
+ ConsoleHelper helper(args, m_inspector);
v8::Local<v8::Object> obj;
if (!helper.firstArgAsObject().ToLocal(&obj)) return;
v8::Local<v8::Array> names;
@@ -414,7 +404,8 @@ void V8Console::valuesCallback(
v8::Isolate* isolate = info.GetIsolate();
info.GetReturnValue().Set(v8::Array::New(isolate));
- ConsoleHelper helper(info, m_inspector);
+ v8::debug::ConsoleCallArguments args(info);
+ ConsoleHelper helper(args, m_inspector);
v8::Local<v8::Object> obj;
if (!helper.firstArgAsObject().ToLocal(&obj)) return;
v8::Local<v8::Array> names;
@@ -453,7 +444,8 @@ static void setFunctionBreakpoint(ConsoleHelper& helper,
void V8Console::debugFunctionCallback(
const v8::FunctionCallbackInfo<v8::Value>& info) {
- ConsoleHelper helper(info, m_inspector);
+ v8::debug::ConsoleCallArguments args(info);
+ ConsoleHelper helper(args, m_inspector);
v8::Local<v8::Function> function;
if (!helper.firstArgAsFunction().ToLocal(&function)) return;
setFunctionBreakpoint(helper, function,
@@ -463,7 +455,8 @@ void V8Console::debugFunctionCallback(
void V8Console::undebugFunctionCallback(
const v8::FunctionCallbackInfo<v8::Value>& info) {
- ConsoleHelper helper(info, m_inspector);
+ v8::debug::ConsoleCallArguments args(info);
+ ConsoleHelper helper(args, m_inspector);
v8::Local<v8::Function> function;
if (!helper.firstArgAsFunction().ToLocal(&function)) return;
setFunctionBreakpoint(helper, function,
@@ -473,7 +466,8 @@ void V8Console::undebugFunctionCallback(
void V8Console::monitorFunctionCallback(
const v8::FunctionCallbackInfo<v8::Value>& info) {
- ConsoleHelper helper(info, m_inspector);
+ v8::debug::ConsoleCallArguments args(info);
+ ConsoleHelper helper(args, m_inspector);
v8::Local<v8::Function> function;
if (!helper.firstArgAsFunction().ToLocal(&function)) return;
v8::Local<v8::Value> name = function->GetName();
@@ -496,7 +490,8 @@ void V8Console::monitorFunctionCallback(
void V8Console::unmonitorFunctionCallback(
const v8::FunctionCallbackInfo<v8::Value>& info) {
- ConsoleHelper helper(info, m_inspector);
+ v8::debug::ConsoleCallArguments args(info);
+ ConsoleHelper helper(args, m_inspector);
v8::Local<v8::Function> function;
if (!helper.firstArgAsFunction().ToLocal(&function)) return;
setFunctionBreakpoint(helper, function,
@@ -506,7 +501,8 @@ void V8Console::unmonitorFunctionCallback(
void V8Console::lastEvaluationResultCallback(
const v8::FunctionCallbackInfo<v8::Value>& info) {
- ConsoleHelper helper(info, m_inspector);
+ v8::debug::ConsoleCallArguments args(info);
+ ConsoleHelper helper(args, m_inspector);
InjectedScript* injectedScript = helper.injectedScript();
if (!injectedScript) return;
info.GetReturnValue().Set(injectedScript->lastEvaluationResult());
@@ -517,7 +513,8 @@ static void inspectImpl(const v8::FunctionCallbackInfo<v8::Value>& info,
if (info.Length() < 1) return;
if (!copyToClipboard) info.GetReturnValue().Set(info[0]);
- ConsoleHelper helper(info, inspector);
+ v8::debug::ConsoleCallArguments args(info);
+ ConsoleHelper helper(args, inspector);
InjectedScript* injectedScript = helper.injectedScript();
if (!injectedScript) return;
std::unique_ptr<protocol::Runtime::RemoteObject> wrappedObject;
@@ -547,7 +544,8 @@ void V8Console::copyCallback(const v8::FunctionCallbackInfo<v8::Value>& info) {
void V8Console::inspectedObject(const v8::FunctionCallbackInfo<v8::Value>& info,
unsigned num) {
DCHECK(num < V8InspectorSessionImpl::kInspectedObjectBufferSize);
- ConsoleHelper helper(info, m_inspector);
+ v8::debug::ConsoleCallArguments args(info);
+ ConsoleHelper helper(args, m_inspector);
if (V8InspectorSessionImpl* session = helper.currentSession()) {
V8InspectorSession::Inspectable* object = session->inspectedObject(num);
v8::Isolate* isolate = info.GetIsolate();
@@ -558,71 +556,6 @@ void V8Console::inspectedObject(const v8::FunctionCallbackInfo<v8::Value>& info,
}
}
-v8::Local<v8::Object> V8Console::createConsole(v8::Local<v8::Context> context) {
- v8::Context::Scope contextScope(context);
- v8::Isolate* isolate = context->GetIsolate();
- v8::MicrotasksScope microtasksScope(isolate,
- v8::MicrotasksScope::kDoNotRunMicrotasks);
-
- v8::Local<v8::Object> console = v8::Object::New(isolate);
- bool success =
- console->SetPrototype(context, v8::Object::New(isolate)).FromMaybe(false);
- DCHECK(success);
- USE(success);
-
- v8::Local<v8::External> data = v8::External::New(isolate, this);
- createBoundFunctionProperty(context, console, data, "debug",
- &V8Console::call<&V8Console::debugCallback>);
- createBoundFunctionProperty(context, console, data, "error",
- &V8Console::call<&V8Console::errorCallback>);
- createBoundFunctionProperty(context, console, data, "info",
- &V8Console::call<&V8Console::infoCallback>);
- createBoundFunctionProperty(context, console, data, "log",
- &V8Console::call<&V8Console::logCallback>);
- createBoundFunctionProperty(context, console, data, "warn",
- &V8Console::call<&V8Console::warnCallback>);
- createBoundFunctionProperty(context, console, data, "dir",
- &V8Console::call<&V8Console::dirCallback>);
- createBoundFunctionProperty(context, console, data, "dirxml",
- &V8Console::call<&V8Console::dirxmlCallback>);
- createBoundFunctionProperty(context, console, data, "table",
- &V8Console::call<&V8Console::tableCallback>);
- createBoundFunctionProperty(context, console, data, "trace",
- &V8Console::call<&V8Console::traceCallback>);
- createBoundFunctionProperty(context, console, data, "group",
- &V8Console::call<&V8Console::groupCallback>);
- createBoundFunctionProperty(
- context, console, data, "groupCollapsed",
- &V8Console::call<&V8Console::groupCollapsedCallback>);
- createBoundFunctionProperty(context, console, data, "groupEnd",
- &V8Console::call<&V8Console::groupEndCallback>);
- createBoundFunctionProperty(context, console, data, "clear",
- &V8Console::call<&V8Console::clearCallback>);
- createBoundFunctionProperty(context, console, data, "count",
- &V8Console::call<&V8Console::countCallback>);
- createBoundFunctionProperty(context, console, data, "assert",
- &V8Console::call<&V8Console::assertCallback>);
- createBoundFunctionProperty(
- context, console, data, "markTimeline",
- &V8Console::call<&V8Console::markTimelineCallback>);
- createBoundFunctionProperty(context, console, data, "profile",
- &V8Console::call<&V8Console::profileCallback>);
- createBoundFunctionProperty(context, console, data, "profileEnd",
- &V8Console::call<&V8Console::profileEndCallback>);
- createBoundFunctionProperty(context, console, data, "timeline",
- &V8Console::call<&V8Console::timelineCallback>);
- createBoundFunctionProperty(
- context, console, data, "timelineEnd",
- &V8Console::call<&V8Console::timelineEndCallback>);
- createBoundFunctionProperty(context, console, data, "time",
- &V8Console::call<&V8Console::timeCallback>);
- createBoundFunctionProperty(context, console, data, "timeEnd",
- &V8Console::call<&V8Console::timeEndCallback>);
- createBoundFunctionProperty(context, console, data, "timeStamp",
- &V8Console::call<&V8Console::timeStampCallback>);
- return console;
-}
-
void V8Console::installMemoryGetter(v8::Local<v8::Context> context,
v8::Local<v8::Object> console) {
v8::Isolate* isolate = context->GetIsolate();
@@ -654,24 +587,24 @@ v8::Local<v8::Object> V8Console::createCommandLineAPI(
v8::Local<v8::External> data = v8::External::New(isolate, this);
createBoundFunctionProperty(context, commandLineAPI, data, "dir",
- &V8Console::call<&V8Console::dirCallback>,
+ &V8Console::call<&V8Console::Dir>,
"function dir(value) { [Command Line API] }");
createBoundFunctionProperty(context, commandLineAPI, data, "dirxml",
- &V8Console::call<&V8Console::dirxmlCallback>,
+ &V8Console::call<&V8Console::DirXml>,
"function dirxml(value) { [Command Line API] }");
createBoundFunctionProperty(context, commandLineAPI, data, "profile",
- &V8Console::call<&V8Console::profileCallback>,
+ &V8Console::call<&V8Console::Profile>,
"function profile(title) { [Command Line API] }");
createBoundFunctionProperty(
context, commandLineAPI, data, "profileEnd",
- &V8Console::call<&V8Console::profileEndCallback>,
+ &V8Console::call<&V8Console::ProfileEnd>,
"function profileEnd(title) { [Command Line API] }");
createBoundFunctionProperty(context, commandLineAPI, data, "clear",
- &V8Console::call<&V8Console::clearCallback>,
+ &V8Console::call<&V8Console::Clear>,
"function clear() { [Command Line API] }");
createBoundFunctionProperty(
context, commandLineAPI, data, "table",
- &V8Console::call<&V8Console::tableCallback>,
+ &V8Console::call<&V8Console::Table>,
"function table(data, [columns]) { [Command Line API] }");
createBoundFunctionProperty(context, commandLineAPI, data, "keys",
diff --git a/deps/v8/src/inspector/v8-console.h b/deps/v8/src/inspector/v8-console.h
index 0b833b3c94..e31133c4e1 100644
--- a/deps/v8/src/inspector/v8-console.h
+++ b/deps/v8/src/inspector/v8-console.h
@@ -8,6 +8,7 @@
#include "src/base/macros.h"
#include "include/v8.h"
+#include "src/debug/interface-types.h"
namespace v8_inspector {
@@ -16,9 +17,8 @@ class V8InspectorImpl;
// Console API
// https://console.spec.whatwg.org/#console-interface
-class V8Console {
+class V8Console : public v8::debug::ConsoleDelegate {
public:
- v8::Local<v8::Object> createConsole(v8::Local<v8::Context> context);
v8::Local<v8::Object> createCommandLineAPI(v8::Local<v8::Context> context);
void installMemoryGetter(v8::Local<v8::Context> context,
v8::Local<v8::Object> console);
@@ -49,29 +49,29 @@ class V8Console {
explicit V8Console(V8InspectorImpl* inspector);
private:
- void debugCallback(const v8::FunctionCallbackInfo<v8::Value>&);
- void errorCallback(const v8::FunctionCallbackInfo<v8::Value>&);
- void infoCallback(const v8::FunctionCallbackInfo<v8::Value>&);
- void logCallback(const v8::FunctionCallbackInfo<v8::Value>&);
- void warnCallback(const v8::FunctionCallbackInfo<v8::Value>&);
- void dirCallback(const v8::FunctionCallbackInfo<v8::Value>&);
- void dirxmlCallback(const v8::FunctionCallbackInfo<v8::Value>&);
- void tableCallback(const v8::FunctionCallbackInfo<v8::Value>&);
- void traceCallback(const v8::FunctionCallbackInfo<v8::Value>&);
- void groupCallback(const v8::FunctionCallbackInfo<v8::Value>&);
- void groupCollapsedCallback(const v8::FunctionCallbackInfo<v8::Value>&);
- void groupEndCallback(const v8::FunctionCallbackInfo<v8::Value>&);
- void clearCallback(const v8::FunctionCallbackInfo<v8::Value>&);
- void countCallback(const v8::FunctionCallbackInfo<v8::Value>&);
- void assertCallback(const v8::FunctionCallbackInfo<v8::Value>&);
- void markTimelineCallback(const v8::FunctionCallbackInfo<v8::Value>&);
- void profileCallback(const v8::FunctionCallbackInfo<v8::Value>&);
- void profileEndCallback(const v8::FunctionCallbackInfo<v8::Value>&);
- void timelineCallback(const v8::FunctionCallbackInfo<v8::Value>&);
- void timelineEndCallback(const v8::FunctionCallbackInfo<v8::Value>&);
- void timeCallback(const v8::FunctionCallbackInfo<v8::Value>&);
- void timeEndCallback(const v8::FunctionCallbackInfo<v8::Value>&);
- void timeStampCallback(const v8::FunctionCallbackInfo<v8::Value>&);
+ void Debug(const v8::debug::ConsoleCallArguments&) override;
+ void Error(const v8::debug::ConsoleCallArguments&) override;
+ void Info(const v8::debug::ConsoleCallArguments&) override;
+ void Log(const v8::debug::ConsoleCallArguments&) override;
+ void Warn(const v8::debug::ConsoleCallArguments&) override;
+ void Dir(const v8::debug::ConsoleCallArguments&) override;
+ void DirXml(const v8::debug::ConsoleCallArguments&) override;
+ void Table(const v8::debug::ConsoleCallArguments&) override;
+ void Trace(const v8::debug::ConsoleCallArguments&) override;
+ void Group(const v8::debug::ConsoleCallArguments&) override;
+ void GroupCollapsed(const v8::debug::ConsoleCallArguments&) override;
+ void GroupEnd(const v8::debug::ConsoleCallArguments&) override;
+ void Clear(const v8::debug::ConsoleCallArguments&) override;
+ void Count(const v8::debug::ConsoleCallArguments&) override;
+ void Assert(const v8::debug::ConsoleCallArguments&) override;
+ void MarkTimeline(const v8::debug::ConsoleCallArguments&) override;
+ void Profile(const v8::debug::ConsoleCallArguments&) override;
+ void ProfileEnd(const v8::debug::ConsoleCallArguments&) override;
+ void Timeline(const v8::debug::ConsoleCallArguments&) override;
+ void TimelineEnd(const v8::debug::ConsoleCallArguments&) override;
+ void Time(const v8::debug::ConsoleCallArguments&) override;
+ void TimeEnd(const v8::debug::ConsoleCallArguments&) override;
+ void TimeStamp(const v8::debug::ConsoleCallArguments&) override;
template <void (V8Console::*func)(const v8::FunctionCallbackInfo<v8::Value>&)>
static void call(const v8::FunctionCallbackInfo<v8::Value>& info) {
@@ -79,6 +79,13 @@ class V8Console {
static_cast<V8Console*>(info.Data().As<v8::External>()->Value());
(console->*func)(info);
}
+ template <void (V8Console::*func)(const v8::debug::ConsoleCallArguments&)>
+ static void call(const v8::FunctionCallbackInfo<v8::Value>& info) {
+ V8Console* console =
+ static_cast<V8Console*>(info.Data().As<v8::External>()->Value());
+ v8::debug::ConsoleCallArguments args(info);
+ (console->*func)(args);
+ }
// TODO(foolip): There is no spec for the Memory Info API, see blink-dev:
// https://groups.google.com/a/chromium.org/d/msg/blink-dev/g5YRCGpC9vs/b4OJz71NmPwJ
diff --git a/deps/v8/src/inspector/v8-debugger-agent-impl.cc b/deps/v8/src/inspector/v8-debugger-agent-impl.cc
index 293c2d43c7..7b03c96c0a 100644
--- a/deps/v8/src/inspector/v8-debugger-agent-impl.cc
+++ b/deps/v8/src/inspector/v8-debugger-agent-impl.cc
@@ -34,7 +34,6 @@ using protocol::Debugger::BreakpointId;
using protocol::Debugger::CallFrame;
using protocol::Runtime::ExceptionDetails;
using protocol::Runtime::ScriptId;
-using protocol::Runtime::StackTrace;
using protocol::Runtime::RemoteObject;
namespace DebuggerAgentState {
@@ -238,7 +237,7 @@ Response V8DebuggerAgentImpl::disable() {
v8::debug::NoBreakOnException);
m_state->setInteger(DebuggerAgentState::asyncCallStackDepth, 0);
- if (isPaused()) m_debugger->continueProgram();
+ if (isPaused()) m_debugger->continueProgram(m_session->contextGroupId());
m_debugger->disable();
JavaScriptCallFrames emptyCallFrames;
m_pausedCallFrames.swap(emptyCallFrames);
@@ -248,7 +247,6 @@ Response V8DebuggerAgentImpl::disable() {
m_scripts.clear();
m_breakpointIdToDebuggerBreakpointIds.clear();
m_debugger->setAsyncCallStackDepth(this, 0);
- m_continueToLocationBreakpointId = String16();
clearBreakDetails();
m_skipAllPauses = false;
m_state->setBoolean(DebuggerAgentState::skipAllPauses, false);
@@ -457,11 +455,15 @@ Response V8DebuggerAgentImpl::getPossibleBreakpoints(
}
auto it = m_scripts.find(scriptId);
if (it == m_scripts.end()) return Response::Error("Script not found");
-
std::vector<v8::debug::BreakLocation> v8Locations;
- if (!it->second->getPossibleBreakpoints(
- v8Start, v8End, restrictToFunction.fromMaybe(false), &v8Locations)) {
- return Response::InternalError();
+ {
+ v8::HandleScope handleScope(m_isolate);
+ v8::Local<v8::Context> debuggerContext =
+ v8::debug::GetDebugContext(m_isolate);
+ v8::Context::Scope contextScope(debuggerContext);
+ v8::TryCatch tryCatch(m_isolate);
+ it->second->getPossibleBreakpoints(
+ v8Start, v8End, restrictToFunction.fromMaybe(false), &v8Locations);
}
*locations = protocol::Array<protocol::Debugger::BreakLocation>::create();
@@ -481,21 +483,14 @@ Response V8DebuggerAgentImpl::getPossibleBreakpoints(
}
Response V8DebuggerAgentImpl::continueToLocation(
- std::unique_ptr<protocol::Debugger::Location> location) {
+ std::unique_ptr<protocol::Debugger::Location> location,
+ Maybe<String16> targetCallFrames) {
if (!enabled()) return Response::Error(kDebuggerNotEnabled);
- if (!m_continueToLocationBreakpointId.isEmpty()) {
- m_debugger->removeBreakpoint(m_continueToLocationBreakpointId);
- m_continueToLocationBreakpointId = "";
- }
-
- ScriptBreakpoint breakpoint(location->getScriptId(),
- location->getLineNumber(),
- location->getColumnNumber(0), String16());
-
- m_continueToLocationBreakpointId = m_debugger->setBreakpoint(
- breakpoint, &breakpoint.line_number, &breakpoint.column_number);
- // TODO(kozyatinskiy): Return actual line and column number.
- return resume();
+ if (!isPaused()) return Response::Error(kDebuggerNotPaused);
+ return m_debugger->continueToLocation(
+ m_session->contextGroupId(), std::move(location),
+ targetCallFrames.fromMaybe(
+ protocol::Debugger::ContinueToLocation::TargetCallFramesEnum::Any));
}
bool V8DebuggerAgentImpl::isFunctionBlackboxed(const String16& scriptId,
@@ -598,7 +593,8 @@ Response V8DebuggerAgentImpl::searchInContent(
Response V8DebuggerAgentImpl::setScriptSource(
const String16& scriptId, const String16& newContent, Maybe<bool> dryRun,
Maybe<protocol::Array<protocol::Debugger::CallFrame>>* newCallFrames,
- Maybe<bool>* stackChanged, Maybe<StackTrace>* asyncStackTrace,
+ Maybe<bool>* stackChanged,
+ Maybe<protocol::Runtime::StackTrace>* asyncStackTrace,
Maybe<protocol::Runtime::ExceptionDetails>* optOutCompileError) {
if (!enabled()) return Response::Error(kDebuggerNotEnabled);
@@ -631,7 +627,7 @@ Response V8DebuggerAgentImpl::setScriptSource(
Response V8DebuggerAgentImpl::restartFrame(
const String16& callFrameId,
std::unique_ptr<Array<CallFrame>>* newCallFrames,
- Maybe<StackTrace>* asyncStackTrace) {
+ Maybe<protocol::Runtime::StackTrace>* asyncStackTrace) {
if (!isPaused()) return Response::Error(kDebuggerNotPaused);
InjectedScript::CallFrameScope scope(m_inspector, m_session->contextGroupId(),
callFrameId);
@@ -715,7 +711,7 @@ Response V8DebuggerAgentImpl::pause() {
Response V8DebuggerAgentImpl::resume() {
if (!isPaused()) return Response::Error(kDebuggerNotPaused);
m_session->releaseObjectGroup(kBacktraceObjectGroup);
- m_debugger->continueProgram();
+ m_debugger->continueProgram(m_session->contextGroupId());
return Response::OK();
}
@@ -1028,11 +1024,14 @@ Response V8DebuggerAgentImpl::currentCallFrames(
return Response::OK();
}
-std::unique_ptr<StackTrace> V8DebuggerAgentImpl::currentAsyncStackTrace() {
- if (!isPaused()) return nullptr;
- V8StackTraceImpl* stackTrace = m_debugger->currentAsyncCallChain();
- return stackTrace ? stackTrace->buildInspectorObjectForTail(m_debugger)
- : nullptr;
+std::unique_ptr<protocol::Runtime::StackTrace>
+V8DebuggerAgentImpl::currentAsyncStackTrace() {
+ std::shared_ptr<AsyncStackTrace> asyncParent =
+ m_debugger->currentAsyncParent();
+ if (!asyncParent) return nullptr;
+ return asyncParent->buildInspectorObject(
+ m_debugger->currentAsyncCreation().get(),
+ m_debugger->maxAsyncCallChainDepth() - 1);
}
bool V8DebuggerAgentImpl::isPaused() const { return m_debugger->isPaused(); }
@@ -1226,11 +1225,6 @@ void V8DebuggerAgentImpl::didPause(int contextId,
m_frontend.paused(std::move(protocolCallFrames), breakReason,
std::move(breakAuxData), std::move(hitBreakpointIds),
currentAsyncStackTrace());
-
- if (!m_continueToLocationBreakpointId.isEmpty()) {
- m_debugger->removeBreakpoint(m_continueToLocationBreakpointId);
- m_continueToLocationBreakpointId = "";
- }
}
void V8DebuggerAgentImpl::didContinue() {
diff --git a/deps/v8/src/inspector/v8-debugger-agent-impl.h b/deps/v8/src/inspector/v8-debugger-agent-impl.h
index 5fa251ca98..c9433e20f6 100644
--- a/deps/v8/src/inspector/v8-debugger-agent-impl.h
+++ b/deps/v8/src/inspector/v8-debugger-agent-impl.h
@@ -23,7 +23,6 @@ class V8DebuggerScript;
class V8InspectorImpl;
class V8InspectorSessionImpl;
class V8Regex;
-class V8StackTraceImpl;
using protocol::Maybe;
using protocol::Response;
@@ -57,8 +56,8 @@ class V8DebuggerAgentImpl : public protocol::Debugger::Backend {
Maybe<String16> optionalCondition, String16*,
std::unique_ptr<protocol::Debugger::Location>* actualLocation) override;
Response removeBreakpoint(const String16& breakpointId) override;
- Response continueToLocation(
- std::unique_ptr<protocol::Debugger::Location>) override;
+ Response continueToLocation(std::unique_ptr<protocol::Debugger::Location>,
+ Maybe<String16> targetCallFrames) override;
Response searchInContent(
const String16& scriptId, const String16& query,
Maybe<bool> optionalCaseSensitive, Maybe<bool> optionalIsRegex,
@@ -185,7 +184,6 @@ class V8DebuggerAgentImpl : public protocol::Debugger::Backend {
ScriptsMap m_scripts;
BreakpointIdToDebuggerBreakpointIdsMap m_breakpointIdToDebuggerBreakpointIds;
DebugServerBreakpointToBreakpointIdAndSourceMap m_serverBreakpoints;
- String16 m_continueToLocationBreakpointId;
using BreakReason =
std::pair<String16, std::unique_ptr<protocol::DictionaryValue>>;
diff --git a/deps/v8/src/inspector/v8-debugger-script.cc b/deps/v8/src/inspector/v8-debugger-script.cc
index d151ab821f..e0aaceb888 100644
--- a/deps/v8/src/inspector/v8-debugger-script.cc
+++ b/deps/v8/src/inspector/v8-debugger-script.cc
@@ -138,11 +138,7 @@ class ActualScript : public V8DebuggerScript {
m_endColumn = m_startColumn;
}
- v8::Local<v8::Value> contextData;
- if (script->ContextData().ToLocal(&contextData) && contextData->IsInt32()) {
- m_executionContextId =
- static_cast<int>(contextData.As<v8::Int32>()->Value());
- }
+ USE(script->ContextId().To(&m_executionContextId));
if (script->Source().ToLocal(&tmp)) {
m_source = toProtocolString(tmp);
diff --git a/deps/v8/src/inspector/v8-debugger.cc b/deps/v8/src/inspector/v8-debugger.cc
index 87c864cd38..86a48401a6 100644
--- a/deps/v8/src/inspector/v8-debugger.cc
+++ b/deps/v8/src/inspector/v8-debugger.cc
@@ -21,9 +21,6 @@ namespace v8_inspector {
namespace {
-// Based on DevTools frontend measurement, with asyncCallStackDepth = 4,
-// average async call stack tail requires ~1 Kb. Let's reserve ~ 128 Mb
-// for async stacks.
static const int kMaxAsyncTaskStacks = 128 * 1024;
inline v8::Local<v8::Boolean> v8Boolean(bool value, v8::Isolate* isolate) {
@@ -32,11 +29,8 @@ inline v8::Local<v8::Boolean> v8Boolean(bool value, v8::Isolate* isolate) {
V8DebuggerAgentImpl* agentForScript(V8InspectorImpl* inspector,
v8::Local<v8::debug::Script> script) {
- v8::Local<v8::Value> contextData;
- if (!script->ContextData().ToLocal(&contextData) || !contextData->IsInt32()) {
- return nullptr;
- }
- int contextId = static_cast<int>(contextData.As<v8::Int32>()->Value());
+ int contextId;
+ if (!script->ContextId().To(&contextId)) return nullptr;
int contextGroupId = inspector->contextGroupId(contextId);
if (!contextGroupId) return nullptr;
return inspector->enabledDebuggerAgentForGroup(contextGroupId);
@@ -136,6 +130,17 @@ v8::MaybeLocal<v8::Object> generatorObjectLocation(
suspendedLocation.GetColumnNumber());
}
+template <typename Map>
+void cleanupExpiredWeakPointers(Map& map) {
+ for (auto it = map.begin(); it != map.end();) {
+ if (it->second.expired()) {
+ it = map.erase(it);
+ } else {
+ ++it;
+ }
+ }
+}
+
} // namespace
static bool inLiveEditScope = false;
@@ -164,10 +169,8 @@ V8Debugger::V8Debugger(v8::Isolate* isolate, V8InspectorImpl* inspector)
m_inspector(inspector),
m_enableCount(0),
m_breakpointsActivated(true),
- m_runningNestedMessageLoop(false),
m_ignoreScriptParsedEventsCounter(0),
m_maxAsyncCallStacks(kMaxAsyncTaskStacks),
- m_lastTaskId(0),
m_maxAsyncCallStackDepth(0),
m_pauseOnExceptionsState(v8::debug::NoBreakOnException),
m_wasmTranslation(isolate) {}
@@ -191,6 +194,7 @@ void V8Debugger::disable() {
if (--m_enableCount) return;
DCHECK(enabled());
clearBreakpoints();
+ clearContinueToLocation();
m_debuggerScript.Reset();
m_debuggerContext.Reset();
allAsyncTasksCanceled();
@@ -212,10 +216,12 @@ void V8Debugger::getCompiledScripts(
for (size_t i = 0; i < scripts.Size(); ++i) {
v8::Local<v8::debug::Script> script = scripts.Get(i);
if (!script->WasCompiled()) continue;
- v8::Local<v8::Value> contextData;
- if (!script->ContextData().ToLocal(&contextData) || !contextData->IsInt32())
+ if (script->IsEmbedded()) {
+ result.push_back(V8DebuggerScript::Create(m_isolate, script, false));
continue;
- int contextId = static_cast<int>(contextData.As<v8::Int32>()->Value());
+ }
+ int contextId;
+ if (!script->ContextId().To(&contextId)) continue;
if (m_inspector->contextGroupId(contextId) != contextGroupId) continue;
result.push_back(V8DebuggerScript::Create(m_isolate, script, false));
}
@@ -358,7 +364,8 @@ bool V8Debugger::breakProgram(int targetContextGroupId) {
return m_inspector->enabledDebuggerAgentForGroup(targetContextGroupId);
}
-void V8Debugger::continueProgram() {
+void V8Debugger::continueProgram(int targetContextGroupId) {
+ if (m_pausedContextGroupId != targetContextGroupId) return;
if (isPaused()) m_inspector->client()->quitMessageLoopOnPause();
m_pausedContext.Clear();
m_executionState.Clear();
@@ -370,7 +377,7 @@ void V8Debugger::stepIntoStatement(int targetContextGroupId) {
DCHECK(targetContextGroupId);
m_targetContextGroupId = targetContextGroupId;
v8::debug::PrepareStep(m_isolate, v8::debug::StepIn);
- continueProgram();
+ continueProgram(targetContextGroupId);
}
void V8Debugger::stepOverStatement(int targetContextGroupId) {
@@ -379,7 +386,7 @@ void V8Debugger::stepOverStatement(int targetContextGroupId) {
DCHECK(targetContextGroupId);
m_targetContextGroupId = targetContextGroupId;
v8::debug::PrepareStep(m_isolate, v8::debug::StepNext);
- continueProgram();
+ continueProgram(targetContextGroupId);
}
void V8Debugger::stepOutOfFunction(int targetContextGroupId) {
@@ -388,7 +395,7 @@ void V8Debugger::stepOutOfFunction(int targetContextGroupId) {
DCHECK(targetContextGroupId);
m_targetContextGroupId = targetContextGroupId;
v8::debug::PrepareStep(m_isolate, v8::debug::StepOut);
- continueProgram();
+ continueProgram(targetContextGroupId);
}
void V8Debugger::scheduleStepIntoAsync(
@@ -405,6 +412,58 @@ void V8Debugger::scheduleStepIntoAsync(
m_stepIntoAsyncCallback = std::move(callback);
}
+Response V8Debugger::continueToLocation(
+ int targetContextGroupId,
+ std::unique_ptr<protocol::Debugger::Location> location,
+ const String16& targetCallFrames) {
+ DCHECK(isPaused());
+ DCHECK(!m_executionState.IsEmpty());
+ DCHECK(targetContextGroupId);
+ m_targetContextGroupId = targetContextGroupId;
+ ScriptBreakpoint breakpoint(location->getScriptId(),
+ location->getLineNumber(),
+ location->getColumnNumber(0), String16());
+ int lineNumber = 0;
+ int columnNumber = 0;
+ m_continueToLocationBreakpointId =
+ setBreakpoint(breakpoint, &lineNumber, &columnNumber);
+ if (!m_continueToLocationBreakpointId.isEmpty()) {
+ m_continueToLocationTargetCallFrames = targetCallFrames;
+ if (m_continueToLocationTargetCallFrames !=
+ protocol::Debugger::ContinueToLocation::TargetCallFramesEnum::Any) {
+ m_continueToLocationStack = captureStackTrace(true);
+ DCHECK(m_continueToLocationStack);
+ }
+ continueProgram(targetContextGroupId);
+ // TODO(kozyatinskiy): Return actual line and column number.
+ return Response::OK();
+ } else {
+ return Response::Error("Cannot continue to specified location");
+ }
+}
+
+bool V8Debugger::shouldContinueToCurrentLocation() {
+ if (m_continueToLocationTargetCallFrames ==
+ protocol::Debugger::ContinueToLocation::TargetCallFramesEnum::Any) {
+ return true;
+ }
+ std::unique_ptr<V8StackTraceImpl> currentStack = captureStackTrace(true);
+ if (m_continueToLocationTargetCallFrames ==
+ protocol::Debugger::ContinueToLocation::TargetCallFramesEnum::Current) {
+ return m_continueToLocationStack->isEqualIgnoringTopFrame(
+ currentStack.get());
+ }
+ return true;
+}
+
+void V8Debugger::clearContinueToLocation() {
+ if (m_continueToLocationBreakpointId.isEmpty()) return;
+ removeBreakpoint(m_continueToLocationBreakpointId);
+ m_continueToLocationBreakpointId = String16();
+ m_continueToLocationTargetCallFrames = String16();
+ m_continueToLocationStack.reset();
+}
+
Response V8Debugger::setScriptSource(
const String16& sourceID, v8::Local<v8::String> newSource, bool dryRun,
Maybe<protocol::Runtime::ExceptionDetails>* exceptionDetails,
@@ -560,11 +619,17 @@ void V8Debugger::handleProgramBreak(v8::Local<v8::Context> pausedContext,
breakpointIds.push_back(String16::fromInteger(
hitBreakpointNumber->Int32Value(debuggerContext()).FromJust()));
}
+ if (breakpointIds.size() == 1 &&
+ breakpointIds[0] == m_continueToLocationBreakpointId) {
+ v8::Context::Scope contextScope(pausedContext);
+ if (!shouldContinueToCurrentLocation()) return;
+ }
}
+ clearContinueToLocation();
m_pausedContext = pausedContext;
m_executionState = executionState;
- m_runningNestedMessageLoop = true;
+ m_pausedContextGroupId = contextGroupId;
agent->didPause(InspectedContext::contextId(pausedContext), exception,
breakpointIds, isPromiseRejection, isUncaught,
m_scheduledOOMBreak);
@@ -576,7 +641,7 @@ void V8Debugger::handleProgramBreak(v8::Local<v8::Context> pausedContext,
CHECK(!context.IsEmpty() &&
context != v8::debug::GetDebugContext(m_isolate));
m_inspector->client()->runMessageLoopOnPause(groupId);
- m_runningNestedMessageLoop = false;
+ m_pausedContextGroupId = 0;
}
// The agent may have been removed in the nested loop.
agent = m_inspector->enabledDebuggerAgentForGroup(groupId);
@@ -643,8 +708,7 @@ bool V8Debugger::IsFunctionBlackboxed(v8::Local<v8::debug::Script> script,
end);
}
-void V8Debugger::PromiseEventOccurred(v8::Local<v8::Context> context,
- v8::debug::PromiseDebugActionType type,
+void V8Debugger::PromiseEventOccurred(v8::debug::PromiseDebugActionType type,
int id, int parentId,
bool createdByUser) {
// Async task events from Promises are given misaligned pointers to prevent
@@ -655,10 +719,7 @@ void V8Debugger::PromiseEventOccurred(v8::Local<v8::Context> context,
switch (type) {
case v8::debug::kDebugPromiseCreated:
asyncTaskCreatedForStack(task, parentTask);
- if (createdByUser && parentTask) {
- v8::Context::Scope contextScope(context);
- asyncTaskCandidateForStepping(task);
- }
+ if (createdByUser && parentTask) asyncTaskCandidateForStepping(task);
break;
case v8::debug::kDebugEnqueueAsyncFunction:
asyncTaskScheduledForStack("async function", task, true);
@@ -669,10 +730,6 @@ void V8Debugger::PromiseEventOccurred(v8::Local<v8::Context> context,
case v8::debug::kDebugEnqueuePromiseReject:
asyncTaskScheduledForStack("Promise.reject", task, true);
break;
- case v8::debug::kDebugPromiseCollected:
- asyncTaskCanceledForStack(task);
- asyncTaskCanceledForStepping(task);
- break;
case v8::debug::kDebugWillHandle:
asyncTaskStartedForStack(task);
asyncTaskStartedForStepping(task);
@@ -684,9 +741,16 @@ void V8Debugger::PromiseEventOccurred(v8::Local<v8::Context> context,
}
}
-V8StackTraceImpl* V8Debugger::currentAsyncCallChain() {
- if (!m_currentStacks.size()) return nullptr;
- return m_currentStacks.back().get();
+std::shared_ptr<AsyncStackTrace> V8Debugger::currentAsyncParent() {
+ // TODO(kozyatinskiy): implement creation chain as parent without hack.
+ if (!m_currentAsyncCreation.empty() && m_currentAsyncCreation.back()) {
+ return m_currentAsyncCreation.back();
+ }
+ return m_currentAsyncParent.empty() ? nullptr : m_currentAsyncParent.back();
+}
+
+std::shared_ptr<AsyncStackTrace> V8Debugger::currentAsyncCreation() {
+ return nullptr;
}
void V8Debugger::compileDebuggerScript() {
@@ -827,8 +891,8 @@ v8::MaybeLocal<v8::Array> V8Debugger::internalProperties(
}
std::unique_ptr<V8StackTraceImpl> V8Debugger::createStackTrace(
- v8::Local<v8::StackTrace> stackTrace) {
- return V8StackTraceImpl::create(this, currentContextGroupId(), stackTrace,
+ v8::Local<v8::StackTrace> v8StackTrace) {
+ return V8StackTraceImpl::create(this, currentContextGroupId(), v8StackTrace,
V8StackTraceImpl::maxCallStackSizeToCapture);
}
@@ -849,31 +913,19 @@ void V8Debugger::setAsyncCallStackDepth(V8DebuggerAgentImpl* agent, int depth) {
if (!maxAsyncCallStackDepth) allAsyncTasksCanceled();
}
-void V8Debugger::registerAsyncTaskIfNeeded(void* task) {
- if (m_taskToId.find(task) != m_taskToId.end()) return;
-
- int id = ++m_lastTaskId;
- m_taskToId[task] = id;
- m_idToTask[id] = task;
- if (static_cast<int>(m_idToTask.size()) > m_maxAsyncCallStacks) {
- void* taskToRemove = m_idToTask.begin()->second;
- asyncTaskCanceledForStack(taskToRemove);
- }
-}
-
void V8Debugger::asyncTaskCreatedForStack(void* task, void* parentTask) {
if (!m_maxAsyncCallStackDepth) return;
if (parentTask) m_parentTask[task] = parentTask;
v8::HandleScope scope(m_isolate);
- // We don't need to pass context group id here because we get this callback
- // from V8 for promise events only.
- // Passing one as maxStackSize forces no async chain for the new stack and
- // allows us to not grow exponentially.
- std::unique_ptr<V8StackTraceImpl> creationStack =
- V8StackTraceImpl::capture(this, 0, 1, String16());
- if (creationStack && !creationStack->isEmpty()) {
- m_asyncTaskCreationStacks[task] = std::move(creationStack);
- registerAsyncTaskIfNeeded(task);
+ std::shared_ptr<AsyncStackTrace> asyncCreation =
+ AsyncStackTrace::capture(this, currentContextGroupId(), String16(),
+ V8StackTraceImpl::maxCallStackSizeToCapture);
+ // Passing one as maxStackSize forces no async chain for the new stack.
+ if (asyncCreation && !asyncCreation->isEmpty()) {
+ m_asyncTaskCreationStacks[task] = asyncCreation;
+ m_allAsyncStacks.push_back(std::move(asyncCreation));
+ ++m_asyncStacksCount;
+ collectOldAsyncStacksIfNeeded();
}
}
@@ -902,13 +954,15 @@ void V8Debugger::asyncTaskScheduledForStack(const String16& taskName,
void* task, bool recurring) {
if (!m_maxAsyncCallStackDepth) return;
v8::HandleScope scope(m_isolate);
- std::unique_ptr<V8StackTraceImpl> chain = V8StackTraceImpl::capture(
- this, currentContextGroupId(),
- V8StackTraceImpl::maxCallStackSizeToCapture, taskName);
- if (chain) {
- m_asyncTaskStacks[task] = std::move(chain);
+ std::shared_ptr<AsyncStackTrace> asyncStack =
+ AsyncStackTrace::capture(this, currentContextGroupId(), taskName,
+ V8StackTraceImpl::maxCallStackSizeToCapture);
+ if (asyncStack) {
+ m_asyncTaskStacks[task] = asyncStack;
if (recurring) m_recurringTasks.insert(task);
- registerAsyncTaskIfNeeded(task);
+ m_allAsyncStacks.push_back(std::move(asyncStack));
+ ++m_asyncStacksCount;
+ collectOldAsyncStacksIfNeeded();
}
}
@@ -918,18 +972,10 @@ void V8Debugger::asyncTaskCanceledForStack(void* task) {
m_recurringTasks.erase(task);
m_parentTask.erase(task);
m_asyncTaskCreationStacks.erase(task);
- auto it = m_taskToId.find(task);
- if (it == m_taskToId.end()) return;
- m_idToTask.erase(it->second);
- m_taskToId.erase(it);
}
void V8Debugger::asyncTaskStartedForStack(void* task) {
if (!m_maxAsyncCallStackDepth) return;
- m_currentTasks.push_back(task);
- auto parentIt = m_parentTask.find(task);
- AsyncTaskToStackTrace::iterator stackIt = m_asyncTaskStacks.find(
- parentIt == m_parentTask.end() ? task : parentIt->second);
// Needs to support following order of events:
// - asyncTaskScheduled
// <-- attached here -->
@@ -937,25 +983,40 @@ void V8Debugger::asyncTaskStartedForStack(void* task) {
// - asyncTaskCanceled <-- canceled before finished
// <-- async stack requested here -->
// - asyncTaskFinished
- std::unique_ptr<V8StackTraceImpl> stack;
- if (stackIt != m_asyncTaskStacks.end() && stackIt->second)
- stack = stackIt->second->cloneImpl();
+ m_currentTasks.push_back(task);
+ auto parentIt = m_parentTask.find(task);
+ AsyncTaskToStackTrace::iterator stackIt = m_asyncTaskStacks.find(
+ parentIt == m_parentTask.end() ? task : parentIt->second);
+ if (stackIt != m_asyncTaskStacks.end()) {
+ m_currentAsyncParent.push_back(stackIt->second.lock());
+ } else {
+ m_currentAsyncParent.emplace_back();
+ }
auto itCreation = m_asyncTaskCreationStacks.find(task);
- if (stack && itCreation != m_asyncTaskCreationStacks.end()) {
- stack->setCreation(itCreation->second->cloneImpl());
+ if (itCreation != m_asyncTaskCreationStacks.end()) {
+ m_currentAsyncCreation.push_back(itCreation->second.lock());
+ // TODO(kozyatinskiy): implement it without hack.
+ if (m_currentAsyncParent.back()) {
+ m_currentAsyncCreation.back()->setDescription(
+ m_currentAsyncParent.back()->description());
+ m_currentAsyncParent.back().reset();
+ }
+ } else {
+ m_currentAsyncCreation.emplace_back();
}
- m_currentStacks.push_back(std::move(stack));
}
void V8Debugger::asyncTaskFinishedForStack(void* task) {
if (!m_maxAsyncCallStackDepth) return;
// We could start instrumenting half way and the stack is empty.
- if (!m_currentStacks.size()) return;
-
+ if (!m_currentTasks.size()) return;
DCHECK(m_currentTasks.back() == task);
m_currentTasks.pop_back();
- m_currentStacks.pop_back();
+ DCHECK(m_currentAsyncParent.size() == m_currentAsyncCreation.size());
+ m_currentAsyncParent.pop_back();
+ m_currentAsyncCreation.pop_back();
+
if (m_recurringTasks.find(task) == m_recurringTasks.end()) {
asyncTaskCanceledForStack(task);
}
@@ -992,13 +1053,15 @@ void V8Debugger::asyncTaskCanceledForStepping(void* task) {
void V8Debugger::allAsyncTasksCanceled() {
m_asyncTaskStacks.clear();
m_recurringTasks.clear();
- m_currentStacks.clear();
+ m_currentAsyncParent.clear();
+ m_currentAsyncCreation.clear();
m_currentTasks.clear();
m_parentTask.clear();
m_asyncTaskCreationStacks.clear();
- m_idToTask.clear();
- m_taskToId.clear();
- m_lastTaskId = 0;
+
+ m_framesCache.clear();
+ m_allAsyncStacks.clear();
+ m_asyncStacksCount = 0;
}
void V8Debugger::muteScriptParsedEvents() {
@@ -1018,11 +1081,10 @@ std::unique_ptr<V8StackTraceImpl> V8Debugger::captureStackTrace(
int contextGroupId = currentContextGroupId();
if (!contextGroupId) return nullptr;
- size_t stackSize =
- fullStack ? V8StackTraceImpl::maxCallStackSizeToCapture : 1;
- if (m_inspector->enabledRuntimeAgentForGroup(contextGroupId))
+ int stackSize = 1;
+ if (fullStack || m_inspector->enabledRuntimeAgentForGroup(contextGroupId)) {
stackSize = V8StackTraceImpl::maxCallStackSizeToCapture;
-
+ }
return V8StackTraceImpl::capture(this, contextGroupId, stackSize);
}
@@ -1031,4 +1093,68 @@ int V8Debugger::currentContextGroupId() {
return m_inspector->contextGroupId(m_isolate->GetCurrentContext());
}
+void V8Debugger::collectOldAsyncStacksIfNeeded() {
+ if (m_asyncStacksCount <= m_maxAsyncCallStacks) return;
+ int halfOfLimitRoundedUp =
+ m_maxAsyncCallStacks / 2 + m_maxAsyncCallStacks % 2;
+ while (m_asyncStacksCount > halfOfLimitRoundedUp) {
+ m_allAsyncStacks.pop_front();
+ --m_asyncStacksCount;
+ }
+ cleanupExpiredWeakPointers(m_asyncTaskStacks);
+ cleanupExpiredWeakPointers(m_asyncTaskCreationStacks);
+ for (auto it = m_recurringTasks.begin(); it != m_recurringTasks.end();) {
+ if (m_asyncTaskStacks.find(*it) == m_asyncTaskStacks.end()) {
+ it = m_recurringTasks.erase(it);
+ } else {
+ ++it;
+ }
+ }
+ for (auto it = m_parentTask.begin(); it != m_parentTask.end();) {
+ if (m_asyncTaskCreationStacks.find(it->second) ==
+ m_asyncTaskCreationStacks.end() &&
+ m_asyncTaskStacks.find(it->second) == m_asyncTaskStacks.end()) {
+ it = m_parentTask.erase(it);
+ } else {
+ ++it;
+ }
+ }
+ cleanupExpiredWeakPointers(m_framesCache);
+}
+
+std::shared_ptr<StackFrame> V8Debugger::symbolize(
+ v8::Local<v8::StackFrame> v8Frame) {
+ auto it = m_framesCache.end();
+ int frameId = 0;
+ if (m_maxAsyncCallStackDepth) {
+ frameId = v8::debug::GetStackFrameId(v8Frame);
+ it = m_framesCache.find(frameId);
+ }
+ if (it != m_framesCache.end() && it->second.lock()) return it->second.lock();
+ std::shared_ptr<StackFrame> frame(new StackFrame(v8Frame));
+ // TODO(clemensh): Figure out a way to do this translation only right before
+ // sending the stack trace over wire.
+ if (v8Frame->IsWasm()) frame->translate(&m_wasmTranslation);
+ if (m_maxAsyncCallStackDepth) {
+ m_framesCache[frameId] = frame;
+ }
+ return frame;
+}
+
+void V8Debugger::setMaxAsyncTaskStacksForTest(int limit) {
+ m_maxAsyncCallStacks = 0;
+ collectOldAsyncStacksIfNeeded();
+ m_maxAsyncCallStacks = limit;
+}
+
+void V8Debugger::dumpAsyncTaskStacksStateForTest() {
+ fprintf(stdout, "Async stacks count: %d\n", m_asyncStacksCount);
+ fprintf(stdout, "Scheduled async tasks: %zu\n", m_asyncTaskStacks.size());
+ fprintf(stdout, "Created async tasks: %zu\n",
+ m_asyncTaskCreationStacks.size());
+ fprintf(stdout, "Async tasks with parent: %zu\n", m_parentTask.size());
+ fprintf(stdout, "Recurring async tasks: %zu\n", m_recurringTasks.size());
+ fprintf(stdout, "\n");
+}
+
} // namespace v8_inspector
diff --git a/deps/v8/src/inspector/v8-debugger.h b/deps/v8/src/inspector/v8-debugger.h
index 83cc8afb0d..a15c288c0d 100644
--- a/deps/v8/src/inspector/v8-debugger.h
+++ b/deps/v8/src/inspector/v8-debugger.h
@@ -5,6 +5,7 @@
#ifndef V8_INSPECTOR_V8DEBUGGER_H_
#define V8_INSPECTOR_V8DEBUGGER_H_
+#include <list>
#include <vector>
#include "src/base/macros.h"
@@ -20,7 +21,10 @@
namespace v8_inspector {
+class AsyncStackTrace;
struct ScriptBreakpoint;
+class StackFrame;
+class V8Debugger;
class V8DebuggerAgentImpl;
class V8InspectorImpl;
class V8StackTraceImpl;
@@ -35,6 +39,7 @@ class V8Debugger : public v8::debug::DebugDelegate {
~V8Debugger();
bool enabled() const;
+ v8::Isolate* isolate() const { return m_isolate; }
String16 setBreakpoint(const ScriptBreakpoint&, int* actualLineNumber,
int* actualColumnNumber);
@@ -46,7 +51,7 @@ class V8Debugger : public v8::debug::DebugDelegate {
void setPauseOnExceptionsState(v8::debug::ExceptionBreakState);
bool canBreakProgram();
bool breakProgram(int targetContextGroupId);
- void continueProgram();
+ void continueProgram(int targetContextGroupId);
void setPauseOnNextStatement(bool, int targetContextGroupId);
void stepIntoStatement(int targetContextGroupId);
@@ -56,6 +61,10 @@ class V8Debugger : public v8::debug::DebugDelegate {
std::unique_ptr<ScheduleStepIntoAsyncCallback> callback,
int targetContextGroupId);
+ Response continueToLocation(int targetContextGroupId,
+ std::unique_ptr<protocol::Debugger::Location>,
+ const String16& targetCallFramess);
+
Response setScriptSource(
const String16& sourceID, v8::Local<v8::String> newSource, bool dryRun,
protocol::Maybe<protocol::Runtime::ExceptionDetails>*,
@@ -72,12 +81,17 @@ class V8Debugger : public v8::debug::DebugDelegate {
void enable();
void disable();
- bool isPaused() const { return m_runningNestedMessageLoop; }
+ bool isPaused() const { return m_pausedContextGroupId; }
v8::Local<v8::Context> pausedContext() { return m_pausedContext; }
int maxAsyncCallChainDepth() { return m_maxAsyncCallStackDepth; }
- V8StackTraceImpl* currentAsyncCallChain();
void setAsyncCallStackDepth(V8DebuggerAgentImpl*, int);
+
+ std::shared_ptr<AsyncStackTrace> currentAsyncParent();
+ std::shared_ptr<AsyncStackTrace> currentAsyncCreation();
+
+ std::shared_ptr<StackFrame> symbolize(v8::Local<v8::StackFrame> v8Frame);
+
std::unique_ptr<V8StackTraceImpl> createStackTrace(v8::Local<v8::StackTrace>);
std::unique_ptr<V8StackTraceImpl> captureStackTrace(bool fullStack);
@@ -98,7 +112,8 @@ class V8Debugger : public v8::debug::DebugDelegate {
WasmTranslation* wasmTranslation() { return &m_wasmTranslation; }
- void setMaxAsyncTaskStacksForTest(int limit) { m_maxAsyncCallStacks = limit; }
+ void setMaxAsyncTaskStacksForTest(int limit);
+ void dumpAsyncTaskStacksStateForTest();
private:
void compileDebuggerScript();
@@ -108,6 +123,8 @@ class V8Debugger : public v8::debug::DebugDelegate {
bool catchExceptions);
v8::Local<v8::Context> debuggerContext() const;
void clearBreakpoints();
+ void clearContinueToLocation();
+ bool shouldContinueToCurrentLocation();
static void v8OOMCallback(void* data);
@@ -143,11 +160,8 @@ class V8Debugger : public v8::debug::DebugDelegate {
void asyncTaskFinishedForStepping(void* task);
void asyncTaskCanceledForStepping(void* task);
- void registerAsyncTaskIfNeeded(void* task);
-
// v8::debug::DebugEventListener implementation.
- void PromiseEventOccurred(v8::Local<v8::Context> context,
- v8::debug::PromiseDebugActionType type, int id,
+ void PromiseEventOccurred(v8::debug::PromiseDebugActionType type, int id,
int parentId, bool createdByUser) override;
void ScriptCompiled(v8::Local<v8::debug::Script> script,
bool has_compile_error) override;
@@ -172,26 +186,36 @@ class V8Debugger : public v8::debug::DebugDelegate {
v8::Global<v8::Context> m_debuggerContext;
v8::Local<v8::Object> m_executionState;
v8::Local<v8::Context> m_pausedContext;
- bool m_runningNestedMessageLoop;
int m_ignoreScriptParsedEventsCounter;
bool m_scheduledOOMBreak = false;
int m_targetContextGroupId = 0;
+ int m_pausedContextGroupId = 0;
+ String16 m_continueToLocationBreakpointId;
+ String16 m_continueToLocationTargetCallFrames;
+ std::unique_ptr<V8StackTraceImpl> m_continueToLocationStack;
using AsyncTaskToStackTrace =
- protocol::HashMap<void*, std::unique_ptr<V8StackTraceImpl>>;
+ protocol::HashMap<void*, std::weak_ptr<AsyncStackTrace>>;
AsyncTaskToStackTrace m_asyncTaskStacks;
AsyncTaskToStackTrace m_asyncTaskCreationStacks;
- int m_maxAsyncCallStacks;
- std::map<int, void*> m_idToTask;
- std::unordered_map<void*, int> m_taskToId;
- int m_lastTaskId;
protocol::HashSet<void*> m_recurringTasks;
+ protocol::HashMap<void*, void*> m_parentTask;
+
+ int m_maxAsyncCallStacks;
int m_maxAsyncCallStackDepth;
+
std::vector<void*> m_currentTasks;
- std::vector<std::unique_ptr<V8StackTraceImpl>> m_currentStacks;
+ std::vector<std::shared_ptr<AsyncStackTrace>> m_currentAsyncParent;
+ std::vector<std::shared_ptr<AsyncStackTrace>> m_currentAsyncCreation;
+
+ void collectOldAsyncStacksIfNeeded();
+ int m_asyncStacksCount = 0;
+ // V8Debugger owns all the async stacks, while most of the other references
+ // are weak, which allows to collect some stacks when there are too many.
+ std::list<std::shared_ptr<AsyncStackTrace>> m_allAsyncStacks;
+ std::map<int, std::weak_ptr<StackFrame>> m_framesCache;
+
protocol::HashMap<V8DebuggerAgentImpl*, int> m_maxAsyncCallStackDepthMap;
- protocol::HashMap<void*, void*> m_parentTask;
- protocol::HashMap<void*, void*> m_firstNextTask;
void* m_taskWithScheduledBreak = nullptr;
std::unique_ptr<ScheduleStepIntoAsyncCallback> m_stepIntoAsyncCallback;
diff --git a/deps/v8/src/inspector/v8-function-call.cc b/deps/v8/src/inspector/v8-function-call.cc
index b8c86d3da0..0fcca70cb7 100644
--- a/deps/v8/src/inspector/v8-function-call.cc
+++ b/deps/v8/src/inspector/v8-function-call.cc
@@ -75,6 +75,8 @@ v8::Local<v8::Value> V8FunctionCall::call(bool& hadException,
}
v8::Local<v8::Value> V8FunctionCall::callWithoutExceptionHandling() {
+ v8::Context::Scope contextScope(m_context);
+
v8::Local<v8::Object> thisObject = v8::Local<v8::Object>::Cast(m_value);
v8::Local<v8::Value> value;
if (!thisObject->Get(m_context, m_name).ToLocal(&value))
diff --git a/deps/v8/src/inspector/v8-inspector-impl.cc b/deps/v8/src/inspector/v8-inspector-impl.cc
index 705fd793de..3c55507c5a 100644
--- a/deps/v8/src/inspector/v8-inspector-impl.cc
+++ b/deps/v8/src/inspector/v8-inspector-impl.cc
@@ -56,9 +56,13 @@ V8InspectorImpl::V8InspectorImpl(v8::Isolate* isolate,
m_debugger(new V8Debugger(isolate, this)),
m_capturingStackTracesCount(0),
m_lastExceptionId(0),
- m_lastContextId(0) {}
+ m_lastContextId(0) {
+ v8::debug::SetConsoleDelegate(m_isolate, console());
+}
-V8InspectorImpl::~V8InspectorImpl() {}
+V8InspectorImpl::~V8InspectorImpl() {
+ v8::debug::SetConsoleDelegate(m_isolate, nullptr);
+}
int V8InspectorImpl::contextGroupId(v8::Local<v8::Context> context) {
return contextGroupId(InspectedContext::contextId(context));
diff --git a/deps/v8/src/inspector/v8-regex.cc b/deps/v8/src/inspector/v8-regex.cc
index 47af70d360..0bab4364c4 100644
--- a/deps/v8/src/inspector/v8-regex.cc
+++ b/deps/v8/src/inspector/v8-regex.cc
@@ -49,6 +49,7 @@ int V8Regex::match(const String16& string, int startFrom,
v8::Isolate* isolate = m_inspector->isolate();
v8::HandleScope handleScope(isolate);
v8::Local<v8::Context> context = m_inspector->regexContext();
+ v8::Context::Scope contextScope(context);
v8::MicrotasksScope microtasks(isolate,
v8::MicrotasksScope::kDoNotRunMicrotasks);
v8::TryCatch tryCatch(isolate);
diff --git a/deps/v8/src/inspector/v8-stack-trace-impl.cc b/deps/v8/src/inspector/v8-stack-trace-impl.cc
index dddad36202..9db6b47caf 100644
--- a/deps/v8/src/inspector/v8-stack-trace-impl.cc
+++ b/deps/v8/src/inspector/v8-stack-trace-impl.cc
@@ -4,12 +4,10 @@
#include "src/inspector/v8-stack-trace-impl.h"
-#include "src/inspector/string-util.h"
-#include "src/inspector/v8-debugger-agent-impl.h"
-#include "src/inspector/v8-debugger.h"
-#include "src/inspector/v8-inspector-impl.h"
+#include <algorithm>
-#include "include/v8-version.h"
+#include "src/inspector/v8-debugger.h"
+#include "src/inspector/wasm-translation.h"
namespace v8_inspector {
@@ -17,270 +15,212 @@ namespace {
static const v8::StackTrace::StackTraceOptions stackTraceOptions =
static_cast<v8::StackTrace::StackTraceOptions>(
- v8::StackTrace::kLineNumber | v8::StackTrace::kColumnOffset |
- v8::StackTrace::kScriptId | v8::StackTrace::kScriptNameOrSourceURL |
- v8::StackTrace::kFunctionName |
+ v8::StackTrace::kDetailed |
v8::StackTrace::kExposeFramesAcrossSecurityOrigins);
-V8StackTraceImpl::Frame toFrame(v8::Local<v8::StackFrame> frame,
- WasmTranslation* wasmTranslation,
- int contextGroupId) {
- String16 scriptId = String16::fromInteger(frame->GetScriptId());
- String16 sourceName;
- v8::Local<v8::String> sourceNameValue(frame->GetScriptNameOrSourceURL());
- if (!sourceNameValue.IsEmpty())
- sourceName = toProtocolString(sourceNameValue);
-
- String16 functionName;
- v8::Local<v8::String> functionNameValue(frame->GetFunctionName());
- if (!functionNameValue.IsEmpty())
- functionName = toProtocolString(functionNameValue);
-
- int sourceLineNumber = frame->GetLineNumber() - 1;
- int sourceColumn = frame->GetColumn() - 1;
- // TODO(clemensh): Figure out a way to do this translation only right before
- // sending the stack trace over wire.
- if (frame->IsWasm()) {
- wasmTranslation->TranslateWasmScriptLocationToProtocolLocation(
- &scriptId, &sourceLineNumber, &sourceColumn);
+std::vector<std::shared_ptr<StackFrame>> toFramesVector(
+ V8Debugger* debugger, v8::Local<v8::StackTrace> v8StackTrace,
+ int maxStackSize) {
+ DCHECK(debugger->isolate()->InContext());
+ int frameCount = std::min(v8StackTrace->GetFrameCount(), maxStackSize);
+ std::vector<std::shared_ptr<StackFrame>> frames;
+ for (int i = 0; i < frameCount; ++i) {
+ frames.push_back(debugger->symbolize(v8StackTrace->GetFrame(i)));
}
- return V8StackTraceImpl::Frame(functionName, scriptId, sourceName,
- sourceLineNumber + 1, sourceColumn + 1);
+ return frames;
}
-void toFramesVector(v8::Local<v8::StackTrace> stackTrace,
- std::vector<V8StackTraceImpl::Frame>& frames,
- size_t maxStackSize, v8::Isolate* isolate,
- V8Debugger* debugger, int contextGroupId) {
- DCHECK(isolate->InContext());
- int frameCount = stackTrace->GetFrameCount();
- if (frameCount > static_cast<int>(maxStackSize))
- frameCount = static_cast<int>(maxStackSize);
- WasmTranslation* wasmTranslation = debugger->wasmTranslation();
- for (int i = 0; i < frameCount; i++) {
- v8::Local<v8::StackFrame> stackFrame = stackTrace->GetFrame(i);
- frames.push_back(toFrame(stackFrame, wasmTranslation, contextGroupId));
+void calculateAsyncChain(V8Debugger* debugger, int contextGroupId,
+ std::shared_ptr<AsyncStackTrace>* asyncParent,
+ std::shared_ptr<AsyncStackTrace>* asyncCreation,
+ int* maxAsyncDepth) {
+ *asyncParent = debugger->currentAsyncParent();
+ *asyncCreation = debugger->currentAsyncCreation();
+ if (maxAsyncDepth) *maxAsyncDepth = debugger->maxAsyncCallChainDepth();
+
+ DCHECK(!*asyncParent || !*asyncCreation ||
+ (*asyncParent)->contextGroupId() ==
+ (*asyncCreation)->contextGroupId());
+ // Do not accidentally append async call chain from another group. This should
+ // not happen if we have proper instrumentation, but let's double-check to be
+ // safe.
+ if (contextGroupId && *asyncParent &&
+ (*asyncParent)->contextGroupId() != contextGroupId) {
+ asyncParent->reset();
+ asyncCreation->reset();
+ if (maxAsyncDepth) *maxAsyncDepth = 0;
+ return;
+ }
+
+ // Only the top stack in the chain may be empty and doesn't contain creation
+ // stack, so ensure that second stack is non-empty (it's the top of appended
+ // chain).
+ if (*asyncParent && !(*asyncCreation) && !(*asyncParent)->creation().lock() &&
+ (*asyncParent)->isEmpty()) {
+ *asyncParent = (*asyncParent)->parent().lock();
}
}
+std::unique_ptr<protocol::Runtime::StackTrace> buildInspectorObjectCommon(
+ const std::vector<std::shared_ptr<StackFrame>>& frames,
+ const String16& description,
+ const std::shared_ptr<AsyncStackTrace>& asyncParent,
+ const std::shared_ptr<AsyncStackTrace>& asyncCreation, int maxAsyncDepth) {
+ if (asyncParent && frames.empty() &&
+ description == asyncParent->description() && !asyncCreation) {
+ return asyncParent->buildInspectorObject(nullptr, maxAsyncDepth);
+ }
+
+ std::unique_ptr<protocol::Array<protocol::Runtime::CallFrame>>
+ inspectorFrames = protocol::Array<protocol::Runtime::CallFrame>::create();
+ for (size_t i = 0; i < frames.size(); i++) {
+ inspectorFrames->addItem(frames[i]->buildInspectorObject());
+ }
+ std::unique_ptr<protocol::Runtime::StackTrace> stackTrace =
+ protocol::Runtime::StackTrace::create()
+ .setCallFrames(std::move(inspectorFrames))
+ .build();
+ if (!description.isEmpty()) stackTrace->setDescription(description);
+ if (asyncParent && maxAsyncDepth > 0) {
+ stackTrace->setParent(asyncParent->buildInspectorObject(asyncCreation.get(),
+ maxAsyncDepth - 1));
+ }
+ return stackTrace;
+}
+
} // namespace
-V8StackTraceImpl::Frame::Frame()
- : m_functionName("undefined"),
- m_scriptId(""),
- m_scriptName("undefined"),
- m_lineNumber(0),
- m_columnNumber(0) {}
-
-V8StackTraceImpl::Frame::Frame(const String16& functionName,
- const String16& scriptId,
- const String16& scriptName, int lineNumber,
- int column)
- : m_functionName(functionName),
- m_scriptId(scriptId),
- m_scriptName(scriptName),
- m_lineNumber(lineNumber),
- m_columnNumber(column) {
- DCHECK(m_lineNumber != v8::Message::kNoLineNumberInfo);
- DCHECK(m_columnNumber != v8::Message::kNoColumnInfo);
+StackFrame::StackFrame(v8::Local<v8::StackFrame> v8Frame)
+ : m_functionName(toProtocolString(v8Frame->GetFunctionName())),
+ m_scriptId(String16::fromInteger(v8Frame->GetScriptId())),
+ m_sourceURL(toProtocolString(v8Frame->GetScriptNameOrSourceURL())),
+ m_lineNumber(v8Frame->GetLineNumber() - 1),
+ m_columnNumber(v8Frame->GetColumn() - 1) {
+ DCHECK(m_lineNumber + 1 != v8::Message::kNoLineNumberInfo);
+ DCHECK(m_columnNumber + 1 != v8::Message::kNoColumnInfo);
}
-V8StackTraceImpl::Frame::~Frame() {}
+void StackFrame::translate(WasmTranslation* wasmTranslation) {
+ wasmTranslation->TranslateWasmScriptLocationToProtocolLocation(
+ &m_scriptId, &m_lineNumber, &m_columnNumber);
+}
+
+const String16& StackFrame::functionName() const { return m_functionName; }
+
+const String16& StackFrame::scriptId() const { return m_scriptId; }
-// buildInspectorObject() and SourceLocation's toTracedValue() should set the
-// same fields.
-// If either of them is modified, the other should be also modified.
-std::unique_ptr<protocol::Runtime::CallFrame>
-V8StackTraceImpl::Frame::buildInspectorObject() const {
+const String16& StackFrame::sourceURL() const { return m_sourceURL; }
+
+int StackFrame::lineNumber() const { return m_lineNumber; }
+
+int StackFrame::columnNumber() const { return m_columnNumber; }
+
+std::unique_ptr<protocol::Runtime::CallFrame> StackFrame::buildInspectorObject()
+ const {
return protocol::Runtime::CallFrame::create()
.setFunctionName(m_functionName)
.setScriptId(m_scriptId)
- .setUrl(m_scriptName)
- .setLineNumber(m_lineNumber - 1)
- .setColumnNumber(m_columnNumber - 1)
+ .setUrl(m_sourceURL)
+ .setLineNumber(m_lineNumber)
+ .setColumnNumber(m_columnNumber)
.build();
}
-V8StackTraceImpl::Frame V8StackTraceImpl::Frame::clone() const {
- return Frame(m_functionName, m_scriptId, m_scriptName, m_lineNumber,
- m_columnNumber);
+bool StackFrame::isEqual(StackFrame* frame) const {
+ return m_scriptId == frame->m_scriptId &&
+ m_lineNumber == frame->m_lineNumber &&
+ m_columnNumber == frame->m_columnNumber;
}
// static
void V8StackTraceImpl::setCaptureStackTraceForUncaughtExceptions(
v8::Isolate* isolate, bool capture) {
isolate->SetCaptureStackTraceForUncaughtExceptions(
- capture, V8StackTraceImpl::maxCallStackSizeToCapture, stackTraceOptions);
+ capture, V8StackTraceImpl::maxCallStackSizeToCapture);
}
// static
std::unique_ptr<V8StackTraceImpl> V8StackTraceImpl::create(
V8Debugger* debugger, int contextGroupId,
- v8::Local<v8::StackTrace> stackTrace, size_t maxStackSize,
- const String16& description) {
+ v8::Local<v8::StackTrace> v8StackTrace, int maxStackSize) {
DCHECK(debugger);
- v8::Isolate* isolate = debugger->inspector()->isolate();
- v8::HandleScope scope(isolate);
- std::vector<V8StackTraceImpl::Frame> frames;
- if (!stackTrace.IsEmpty())
- toFramesVector(stackTrace, frames, maxStackSize, isolate, debugger,
- contextGroupId);
-
- int maxAsyncCallChainDepth = 1;
- V8StackTraceImpl* asyncCallChain = nullptr;
- if (maxStackSize > 1) {
- asyncCallChain = debugger->currentAsyncCallChain();
- maxAsyncCallChainDepth = debugger->maxAsyncCallChainDepth();
- }
- // Do not accidentally append async call chain from another group. This should
- // not
- // happen if we have proper instrumentation, but let's double-check to be
- // safe.
- if (contextGroupId && asyncCallChain && asyncCallChain->m_contextGroupId &&
- asyncCallChain->m_contextGroupId != contextGroupId) {
- asyncCallChain = nullptr;
- maxAsyncCallChainDepth = 1;
- }
-
- // Only the top stack in the chain may be empty and doesn't contain creation
- // stack , so ensure that second stack is non-empty (it's the top of appended
- // chain).
- if (asyncCallChain && asyncCallChain->isEmpty() &&
- !asyncCallChain->m_creation) {
- asyncCallChain = asyncCallChain->m_parent.get();
- }
-
- if (stackTrace.IsEmpty() && !asyncCallChain) return nullptr;
- std::unique_ptr<V8StackTraceImpl> result(new V8StackTraceImpl(
- contextGroupId, description, frames,
- asyncCallChain ? asyncCallChain->cloneImpl() : nullptr));
+ v8::Isolate* isolate = debugger->isolate();
+ v8::HandleScope scope(isolate);
- // Crop to not exceed maxAsyncCallChainDepth.
- V8StackTraceImpl* deepest = result.get();
- while (deepest && maxAsyncCallChainDepth) {
- deepest = deepest->m_parent.get();
- maxAsyncCallChainDepth--;
+ std::vector<std::shared_ptr<StackFrame>> frames;
+ if (!v8StackTrace.IsEmpty() && v8StackTrace->GetFrameCount()) {
+ frames = toFramesVector(debugger, v8StackTrace, maxStackSize);
}
- if (deepest) deepest->m_parent.reset();
- return result;
+ int maxAsyncDepth = 0;
+ std::shared_ptr<AsyncStackTrace> asyncParent;
+ std::shared_ptr<AsyncStackTrace> asyncCreation;
+ calculateAsyncChain(debugger, contextGroupId, &asyncParent, &asyncCreation,
+ &maxAsyncDepth);
+ if (frames.empty() && !asyncCreation && !asyncParent) return nullptr;
+ return std::unique_ptr<V8StackTraceImpl>(new V8StackTraceImpl(
+ std::move(frames), maxAsyncDepth, asyncParent, asyncCreation));
}
// static
std::unique_ptr<V8StackTraceImpl> V8StackTraceImpl::capture(
- V8Debugger* debugger, int contextGroupId, size_t maxStackSize,
- const String16& description) {
+ V8Debugger* debugger, int contextGroupId, int maxStackSize) {
DCHECK(debugger);
- v8::Isolate* isolate = debugger->inspector()->isolate();
+ v8::Isolate* isolate = debugger->isolate();
v8::HandleScope handleScope(isolate);
- v8::Local<v8::StackTrace> stackTrace;
+ v8::Local<v8::StackTrace> v8StackTrace;
if (isolate->InContext()) {
- stackTrace = v8::StackTrace::CurrentStackTrace(
- isolate, static_cast<int>(maxStackSize), stackTraceOptions);
+ v8StackTrace = v8::StackTrace::CurrentStackTrace(isolate, maxStackSize,
+ stackTraceOptions);
}
- return V8StackTraceImpl::create(debugger, contextGroupId, stackTrace,
- maxStackSize, description);
+ return V8StackTraceImpl::create(debugger, contextGroupId, v8StackTrace,
+ maxStackSize);
}
-std::unique_ptr<V8StackTraceImpl> V8StackTraceImpl::cloneImpl() {
- std::vector<Frame> framesCopy(m_frames);
- std::unique_ptr<V8StackTraceImpl> copy(
- new V8StackTraceImpl(m_contextGroupId, m_description, framesCopy,
- m_parent ? m_parent->cloneImpl() : nullptr));
- if (m_creation) copy->setCreation(m_creation->cloneImpl());
- return copy;
-}
-
-std::unique_ptr<V8StackTrace> V8StackTraceImpl::clone() {
- std::vector<Frame> frames;
- for (size_t i = 0; i < m_frames.size(); i++)
- frames.push_back(m_frames.at(i).clone());
- return std::unique_ptr<V8StackTraceImpl>(
- new V8StackTraceImpl(m_contextGroupId, m_description, frames, nullptr));
-}
-
-V8StackTraceImpl::V8StackTraceImpl(int contextGroupId,
- const String16& description,
- std::vector<Frame>& frames,
- std::unique_ptr<V8StackTraceImpl> parent)
- : m_contextGroupId(contextGroupId),
- m_description(description),
- m_parent(std::move(parent)) {
- m_frames.swap(frames);
-}
+V8StackTraceImpl::V8StackTraceImpl(
+ std::vector<std::shared_ptr<StackFrame>> frames, int maxAsyncDepth,
+ std::shared_ptr<AsyncStackTrace> asyncParent,
+ std::shared_ptr<AsyncStackTrace> asyncCreation)
+ : m_frames(std::move(frames)),
+ m_maxAsyncDepth(maxAsyncDepth),
+ m_asyncParent(asyncParent),
+ m_asyncCreation(asyncCreation) {}
V8StackTraceImpl::~V8StackTraceImpl() {}
-void V8StackTraceImpl::setCreation(std::unique_ptr<V8StackTraceImpl> creation) {
- m_creation = std::move(creation);
- // When async call chain is empty but doesn't contain useful schedule stack
- // and parent async call chain contains creationg stack but doesn't
- // synchronous we can merge them together.
- // e.g. Promise ThenableJob.
- if (m_parent && isEmpty() && m_description == m_parent->m_description &&
- !m_parent->m_creation) {
- m_frames.swap(m_parent->m_frames);
- m_parent = std::move(m_parent->m_parent);
- }
+std::unique_ptr<V8StackTrace> V8StackTraceImpl::clone() {
+ return std::unique_ptr<V8StackTrace>(
+ new V8StackTraceImpl(m_frames, 0, std::shared_ptr<AsyncStackTrace>(),
+ std::shared_ptr<AsyncStackTrace>()));
}
+bool V8StackTraceImpl::isEmpty() const { return m_frames.empty(); }
+
StringView V8StackTraceImpl::topSourceURL() const {
- DCHECK(m_frames.size());
- return toStringView(m_frames[0].m_scriptName);
+ return toStringView(m_frames[0]->sourceURL());
}
int V8StackTraceImpl::topLineNumber() const {
- DCHECK(m_frames.size());
- return m_frames[0].m_lineNumber;
+ return m_frames[0]->lineNumber() + 1;
}
int V8StackTraceImpl::topColumnNumber() const {
- DCHECK(m_frames.size());
- return m_frames[0].m_columnNumber;
-}
-
-StringView V8StackTraceImpl::topFunctionName() const {
- DCHECK(m_frames.size());
- return toStringView(m_frames[0].m_functionName);
+ return m_frames[0]->columnNumber() + 1;
}
StringView V8StackTraceImpl::topScriptId() const {
- DCHECK(m_frames.size());
- return toStringView(m_frames[0].m_scriptId);
+ return toStringView(m_frames[0]->scriptId());
}
-std::unique_ptr<protocol::Runtime::StackTrace>
-V8StackTraceImpl::buildInspectorObjectImpl() const {
- std::unique_ptr<protocol::Array<protocol::Runtime::CallFrame>> frames =
- protocol::Array<protocol::Runtime::CallFrame>::create();
- for (size_t i = 0; i < m_frames.size(); i++)
- frames->addItem(m_frames.at(i).buildInspectorObject());
-
- std::unique_ptr<protocol::Runtime::StackTrace> stackTrace =
- protocol::Runtime::StackTrace::create()
- .setCallFrames(std::move(frames))
- .build();
- if (!m_description.isEmpty()) stackTrace->setDescription(m_description);
- if (m_parent) stackTrace->setParent(m_parent->buildInspectorObjectImpl());
- if (m_creation && m_creation->m_frames.size()) {
- stackTrace->setPromiseCreationFrame(
- m_creation->m_frames[0].buildInspectorObject());
- }
- return stackTrace;
+StringView V8StackTraceImpl::topFunctionName() const {
+ return toStringView(m_frames[0]->functionName());
}
std::unique_ptr<protocol::Runtime::StackTrace>
-V8StackTraceImpl::buildInspectorObjectForTail(V8Debugger* debugger) const {
- DCHECK(debugger);
- v8::HandleScope handleScope(debugger->inspector()->isolate());
- // Next call collapses possible empty stack and ensures
- // maxAsyncCallChainDepth.
- std::unique_ptr<V8StackTraceImpl> fullChain = V8StackTraceImpl::create(
- debugger, m_contextGroupId, v8::Local<v8::StackTrace>(),
- V8StackTraceImpl::maxCallStackSizeToCapture);
- if (!fullChain || !fullChain->m_parent) return nullptr;
- return fullChain->m_parent->buildInspectorObjectImpl();
+V8StackTraceImpl::buildInspectorObjectImpl() const {
+ return buildInspectorObjectCommon(m_frames, String16(), m_asyncParent.lock(),
+ m_asyncCreation.lock(), m_maxAsyncDepth);
}
std::unique_ptr<protocol::Runtime::API::StackTrace>
@@ -291,20 +231,139 @@ V8StackTraceImpl::buildInspectorObject() const {
std::unique_ptr<StringBuffer> V8StackTraceImpl::toString() const {
String16Builder stackTrace;
for (size_t i = 0; i < m_frames.size(); ++i) {
- const Frame& frame = m_frames[i];
+ const StackFrame& frame = *m_frames[i];
stackTrace.append("\n at " + (frame.functionName().length()
? frame.functionName()
: "(anonymous function)"));
stackTrace.append(" (");
stackTrace.append(frame.sourceURL());
stackTrace.append(':');
- stackTrace.append(String16::fromInteger(frame.lineNumber()));
+ stackTrace.append(String16::fromInteger(frame.lineNumber() + 1));
stackTrace.append(':');
- stackTrace.append(String16::fromInteger(frame.columnNumber()));
+ stackTrace.append(String16::fromInteger(frame.columnNumber() + 1));
stackTrace.append(')');
}
String16 string = stackTrace.toString();
return StringBufferImpl::adopt(string);
}
+bool V8StackTraceImpl::isEqualIgnoringTopFrame(
+ V8StackTraceImpl* stackTrace) const {
+ StackFrameIterator current(this);
+ StackFrameIterator target(stackTrace);
+
+ current.next();
+ target.next();
+ while (!current.done() && !target.done()) {
+ if (!current.frame()->isEqual(target.frame())) {
+ return false;
+ }
+ current.next();
+ target.next();
+ }
+ return current.done() == target.done();
+}
+
+V8StackTraceImpl::StackFrameIterator::StackFrameIterator(
+ const V8StackTraceImpl* stackTrace)
+ : m_currentIt(stackTrace->m_frames.begin()),
+ m_currentEnd(stackTrace->m_frames.end()),
+ m_parent(stackTrace->m_asyncParent.lock().get()) {}
+
+void V8StackTraceImpl::StackFrameIterator::next() {
+ if (m_currentIt == m_currentEnd) return;
+ ++m_currentIt;
+ while (m_currentIt == m_currentEnd && m_parent) {
+ const std::vector<std::shared_ptr<StackFrame>>& frames = m_parent->frames();
+ m_currentIt = frames.begin();
+ if (m_parent->description() == "async function") ++m_currentIt;
+ m_currentEnd = frames.end();
+ m_parent = m_parent->parent().lock().get();
+ }
+}
+
+bool V8StackTraceImpl::StackFrameIterator::done() {
+ return m_currentIt == m_currentEnd;
+}
+
+StackFrame* V8StackTraceImpl::StackFrameIterator::frame() {
+ return m_currentIt->get();
+}
+
+// static
+std::shared_ptr<AsyncStackTrace> AsyncStackTrace::capture(
+ V8Debugger* debugger, int contextGroupId, const String16& description,
+ int maxStackSize) {
+ DCHECK(debugger);
+
+ v8::Isolate* isolate = debugger->isolate();
+ v8::HandleScope handleScope(isolate);
+
+ std::vector<std::shared_ptr<StackFrame>> frames;
+ if (isolate->InContext()) {
+ v8::Local<v8::StackTrace> v8StackTrace = v8::StackTrace::CurrentStackTrace(
+ isolate, maxStackSize, stackTraceOptions);
+ frames = toFramesVector(debugger, v8StackTrace, maxStackSize);
+ }
+
+ std::shared_ptr<AsyncStackTrace> asyncParent;
+ std::shared_ptr<AsyncStackTrace> asyncCreation;
+ calculateAsyncChain(debugger, contextGroupId, &asyncParent, &asyncCreation,
+ nullptr);
+
+ if (frames.empty() && !asyncCreation && !asyncParent) return nullptr;
+
+ // When async call chain is empty but doesn't contain useful schedule stack
+ // and parent async call chain contains creationg stack but doesn't
+ // synchronous we can merge them together.
+ // e.g. Promise ThenableJob.
+ if (asyncParent && frames.empty() &&
+ asyncParent->m_description == description && !asyncCreation) {
+ return asyncParent;
+ }
+
+ DCHECK(contextGroupId || asyncParent);
+ if (!contextGroupId && asyncParent) {
+ contextGroupId = asyncParent->m_contextGroupId;
+ }
+ return std::shared_ptr<AsyncStackTrace>(
+ new AsyncStackTrace(contextGroupId, description, std::move(frames),
+ asyncParent, asyncCreation));
+}
+
+AsyncStackTrace::AsyncStackTrace(
+ int contextGroupId, const String16& description,
+ std::vector<std::shared_ptr<StackFrame>> frames,
+ std::shared_ptr<AsyncStackTrace> asyncParent,
+ std::shared_ptr<AsyncStackTrace> asyncCreation)
+ : m_contextGroupId(contextGroupId),
+ m_description(description),
+ m_frames(std::move(frames)),
+ m_asyncParent(asyncParent),
+ m_asyncCreation(asyncCreation) {
+ DCHECK(m_contextGroupId);
+}
+
+std::unique_ptr<protocol::Runtime::StackTrace>
+AsyncStackTrace::buildInspectorObject(AsyncStackTrace* asyncCreation,
+ int maxAsyncDepth) const {
+ return buildInspectorObjectCommon(m_frames, m_description,
+ m_asyncParent.lock(),
+ m_asyncCreation.lock(), maxAsyncDepth);
+}
+
+int AsyncStackTrace::contextGroupId() const { return m_contextGroupId; }
+
+const String16& AsyncStackTrace::description() const { return m_description; }
+
+std::weak_ptr<AsyncStackTrace> AsyncStackTrace::parent() const {
+ return m_asyncParent;
+}
+
+std::weak_ptr<AsyncStackTrace> AsyncStackTrace::creation() const {
+ return m_asyncCreation;
+}
+
+bool AsyncStackTrace::isEmpty() const { return m_frames.empty(); }
+
} // namespace v8_inspector
diff --git a/deps/v8/src/inspector/v8-stack-trace-impl.h b/deps/v8/src/inspector/v8-stack-trace-impl.h
index f8b53d0a65..5ce051bd5c 100644
--- a/deps/v8/src/inspector/v8-stack-trace-impl.h
+++ b/deps/v8/src/inspector/v8-stack-trace-impl.h
@@ -5,96 +5,142 @@
#ifndef V8_INSPECTOR_V8STACKTRACEIMPL_H_
#define V8_INSPECTOR_V8STACKTRACEIMPL_H_
+#include <memory>
#include <vector>
+#include "include/v8-inspector.h"
+#include "include/v8.h"
#include "src/base/macros.h"
-#include "src/inspector/protocol/Forward.h"
#include "src/inspector/protocol/Runtime.h"
-
-#include "include/v8-inspector.h"
+#include "src/inspector/string-16.h"
namespace v8_inspector {
-class TracedValue;
+class AsyncStackTrace;
class V8Debugger;
+class WasmTranslation;
-// Note: async stack trace may have empty top stack with non-empty tail to
-// indicate
-// that current native-only state had some async story.
-// On the other hand, any non-top async stack is guaranteed to be non-empty.
-class V8StackTraceImpl final : public V8StackTrace {
+class StackFrame {
public:
- static const size_t maxCallStackSizeToCapture = 200;
+ explicit StackFrame(v8::Local<v8::StackFrame> frame);
+ ~StackFrame() = default;
- class Frame {
- public:
- Frame();
- Frame(const String16& functionName, const String16& scriptId,
- const String16& scriptName, int lineNumber, int column = 0);
- ~Frame();
-
- const String16& functionName() const { return m_functionName; }
- const String16& scriptId() const { return m_scriptId; }
- const String16& sourceURL() const { return m_scriptName; }
- int lineNumber() const { return m_lineNumber; }
- int columnNumber() const { return m_columnNumber; }
- Frame clone() const;
+ void translate(WasmTranslation* wasmTranslation);
- private:
- friend class V8StackTraceImpl;
- std::unique_ptr<protocol::Runtime::CallFrame> buildInspectorObject() const;
- void toTracedValue(TracedValue*) const;
-
- String16 m_functionName;
- String16 m_scriptId;
- String16 m_scriptName;
- int m_lineNumber;
- int m_columnNumber;
- };
+ const String16& functionName() const;
+ const String16& scriptId() const;
+ const String16& sourceURL() const;
+ int lineNumber() const; // 0-based.
+ int columnNumber() const; // 0-based.
+ std::unique_ptr<protocol::Runtime::CallFrame> buildInspectorObject() const;
+ bool isEqual(StackFrame* frame) const;
+
+ private:
+ String16 m_functionName;
+ String16 m_scriptId;
+ String16 m_sourceURL;
+ int m_lineNumber; // 0-based.
+ int m_columnNumber; // 0-based.
+};
+class V8StackTraceImpl : public V8StackTrace {
+ public:
static void setCaptureStackTraceForUncaughtExceptions(v8::Isolate*,
bool capture);
- static std::unique_ptr<V8StackTraceImpl> create(
- V8Debugger*, int contextGroupId, v8::Local<v8::StackTrace>,
- size_t maxStackSize, const String16& description = String16());
- static std::unique_ptr<V8StackTraceImpl> capture(
- V8Debugger*, int contextGroupId, size_t maxStackSize,
- const String16& description = String16());
-
- // This method drops the async chain. Use cloneImpl() instead.
- std::unique_ptr<V8StackTrace> clone() override;
- std::unique_ptr<V8StackTraceImpl> cloneImpl();
- std::unique_ptr<protocol::Runtime::StackTrace> buildInspectorObjectForTail(
- V8Debugger*) const;
+ static const int maxCallStackSizeToCapture = 200;
+ static std::unique_ptr<V8StackTraceImpl> create(V8Debugger*,
+ int contextGroupId,
+ v8::Local<v8::StackTrace>,
+ int maxStackSize);
+ static std::unique_ptr<V8StackTraceImpl> capture(V8Debugger*,
+ int contextGroupId,
+ int maxStackSize);
+
+ ~V8StackTraceImpl() override;
std::unique_ptr<protocol::Runtime::StackTrace> buildInspectorObjectImpl()
const;
- ~V8StackTraceImpl() override;
// V8StackTrace implementation.
- bool isEmpty() const override { return !m_frames.size(); };
+ // This method drops the async stack trace.
+ std::unique_ptr<V8StackTrace> clone() override;
+ bool isEmpty() const override;
StringView topSourceURL() const override;
- int topLineNumber() const override;
- int topColumnNumber() const override;
+ int topLineNumber() const override; // 1-based.
+ int topColumnNumber() const override; // 1-based.
StringView topScriptId() const override;
StringView topFunctionName() const override;
std::unique_ptr<protocol::Runtime::API::StackTrace> buildInspectorObject()
const override;
std::unique_ptr<StringBuffer> toString() const override;
- void setCreation(std::unique_ptr<V8StackTraceImpl> creation);
+ bool isEqualIgnoringTopFrame(V8StackTraceImpl* stackTrace) const;
private:
- V8StackTraceImpl(int contextGroupId, const String16& description,
- std::vector<Frame>& frames,
- std::unique_ptr<V8StackTraceImpl> parent);
+ V8StackTraceImpl(std::vector<std::shared_ptr<StackFrame>> frames,
+ int maxAsyncDepth,
+ std::shared_ptr<AsyncStackTrace> asyncParent,
+ std::shared_ptr<AsyncStackTrace> asyncCreation);
+
+ class StackFrameIterator {
+ public:
+ explicit StackFrameIterator(const V8StackTraceImpl* stackTrace);
+
+ void next();
+ StackFrame* frame();
+ bool done();
+
+ private:
+ std::vector<std::shared_ptr<StackFrame>>::const_iterator m_currentIt;
+ std::vector<std::shared_ptr<StackFrame>>::const_iterator m_currentEnd;
+ AsyncStackTrace* m_parent;
+ };
+
+ std::vector<std::shared_ptr<StackFrame>> m_frames;
+ int m_maxAsyncDepth;
+ std::weak_ptr<AsyncStackTrace> m_asyncParent;
+ std::weak_ptr<AsyncStackTrace> m_asyncCreation;
+
+ DISALLOW_COPY_AND_ASSIGN(V8StackTraceImpl);
+};
+
+class AsyncStackTrace {
+ public:
+ static std::shared_ptr<AsyncStackTrace> capture(V8Debugger*,
+ int contextGroupId,
+ const String16& description,
+ int maxStackSize);
+
+ std::unique_ptr<protocol::Runtime::StackTrace> buildInspectorObject(
+ AsyncStackTrace* asyncCreation, int maxAsyncDepth) const;
+
+ int contextGroupId() const;
+ const String16& description() const;
+ std::weak_ptr<AsyncStackTrace> parent() const;
+ std::weak_ptr<AsyncStackTrace> creation() const;
+ bool isEmpty() const;
+
+ void setDescription(const String16& description) {
+ // TODO(kozyatinskiy): implement it without hack.
+ m_description = description;
+ }
+ const std::vector<std::shared_ptr<StackFrame>>& frames() const {
+ return m_frames;
+ }
+
+ private:
+ AsyncStackTrace(int contextGroupId, const String16& description,
+ std::vector<std::shared_ptr<StackFrame>> frames,
+ std::shared_ptr<AsyncStackTrace> asyncParent,
+ std::shared_ptr<AsyncStackTrace> asyncCreation);
int m_contextGroupId;
String16 m_description;
- std::vector<Frame> m_frames;
- std::unique_ptr<V8StackTraceImpl> m_parent;
- std::unique_ptr<V8StackTraceImpl> m_creation;
- DISALLOW_COPY_AND_ASSIGN(V8StackTraceImpl);
+ std::vector<std::shared_ptr<StackFrame>> m_frames;
+ std::weak_ptr<AsyncStackTrace> m_asyncParent;
+ std::weak_ptr<AsyncStackTrace> m_asyncCreation;
+
+ DISALLOW_COPY_AND_ASSIGN(AsyncStackTrace);
};
} // namespace v8_inspector