Commit 4379533c authored by Clemens Hammacher's avatar Clemens Hammacher Committed by Commit Bot

Revert "[inspector] introduced stackTraceId and externalAsyncTask API"

This reverts commit 3a41b697.

Reason for revert: Break msvc: https://build.chromium.org/p/client.v8/builders/V8%20Win64%20-%20msvc/builds/250

Original change's description:
> [inspector] introduced stackTraceId and externalAsyncTask API
> 
> Sometimes we need to capture stack trace on one debugger and use it
> later as a parent stack on another debugger (e.g. worker.postMessage).
> 
> This CL includes following addition to our protocol and v8-inspector.h:
>   - added Runtime.StackTraceId, this id represents stack trace captured
>     on debugger with given id,
>   - protocol client can fetch Runtime.StackTrace by
>     Runtime.StacKTraceId using Debugger.getStackTrace method,
>   - externalParent field is added to Debugger.paused event, it may
>     contain external parent stack trace,
>   - V8Inspector::storeCurrentStackTrace captures current stack trace
>     and returns V8StackTraceId for embedder this id can be used as
>     argument for V8Inspector::externalAsyncTaskStarted and
>     V8Inspector::externalAsyncTaskFinished method. Any async stack
>     trace captured between these calls will get passed external stack
>     trace as external parent. These methods are designed to be called
>     on different debuggers. If async task is scheduled and started on
>     one debugger user should continue to use asyncTask* API,
>   - Debugger.enable methods returns unique debuggerId.
> 
> Bug: chromium:778796
> Cq-Include-Trybots: master.tryserver.blink:linux_trusty_blink_rel;master.tryserver.chromium.linux:linux_chromium_rel_ng
> Change-Id: I16aba0d04bfcea90f3e187e635a0588c92354539
> Reviewed-on: https://chromium-review.googlesource.com/754183
> Reviewed-by: Jakob Gruber <jgruber@chromium.org>
> Reviewed-by: Dmitry Gozman <dgozman@chromium.org>
> Commit-Queue: Aleksey Kozyatinskiy <kozyatinskiy@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#49582}

TBR=dgozman@chromium.org,pfeldman@chromium.org,yangguo@chromium.org,kozyatinskiy@chromium.org,jgruber@chromium.org

Change-Id: I9b52354fa0841e5148596cf594317f2e5fe508ea
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: chromium:778796
Cq-Include-Trybots: master.tryserver.blink:linux_trusty_blink_rel;master.tryserver.chromium.linux:linux_chromium_rel_ng
Reviewed-on: https://chromium-review.googlesource.com/786152Reviewed-by: 's avatarClemens Hammacher <clemensh@chromium.org>
Commit-Queue: Clemens Hammacher <clemensh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#49584}
parent 00a781db
......@@ -215,20 +215,6 @@ class V8_EXPORT V8InspectorClient {
virtual void maxAsyncCallStackDepthChanged(int depth) {}
};
// These stack trace ids are intended to be passed between debuggers and be
// resolved later. This allows to track cross-debugger calls and step between
// them if a single client connects to multiple debuggers.
struct V8_EXPORT V8StackTraceId {
uintptr_t id;
std::pair<int64_t, int64_t> debugger_id;
V8StackTraceId();
V8StackTraceId(uintptr_t id, const std::pair<int64_t, int64_t> debugger_id);
~V8StackTraceId() = default;
bool IsInvalid() const;
};
class V8_EXPORT V8Inspector {
public:
static std::unique_ptr<V8Inspector> create(v8::Isolate*, V8InspectorClient*);
......@@ -251,11 +237,6 @@ class V8_EXPORT V8Inspector {
virtual void asyncTaskFinished(void* task) = 0;
virtual void allAsyncTasksCanceled() = 0;
virtual V8StackTraceId storeCurrentStackTrace(
const StringView& description) = 0;
virtual void externalAsyncTaskStarted(const V8StackTraceId& parent) = 0;
virtual void externalAsyncTaskFinished(const V8StackTraceId& parent) = 0;
// Exceptions instrumentation.
virtual unsigned exceptionThrown(
v8::Local<v8::Context>, const StringView& message,
......
......@@ -10147,12 +10147,6 @@ int debug::GetNativeAccessorDescriptor(v8::Local<v8::Context> context,
return result;
}
int64_t debug::GetNextRandomInt64(v8::Isolate* v8_isolate) {
return reinterpret_cast<i::Isolate*>(v8_isolate)
->random_number_generator()
->NextInt64();
}
Local<String> CpuProfileNode::GetFunctionName() const {
const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
i::Isolate* isolate = node->isolate();
......
......@@ -498,8 +498,6 @@ int GetNativeAccessorDescriptor(v8::Local<v8::Context> context,
v8::Local<v8::Object> object,
v8::Local<v8::Name> name);
int64_t GetNextRandomInt64(v8::Isolate* isolate);
} // namespace debug
} // namespace v8
......
......@@ -12,7 +12,7 @@
{
"domain": "Runtime",
"async": ["evaluate", "awaitPromise", "callFunctionOn", "runScript"],
"exported": ["StackTrace", "StackTraceId", "RemoteObject", "ExecutionContextId"]
"exported": ["StackTrace", "RemoteObject", "ExecutionContextId"]
},
{
"domain": "Debugger",
......
......@@ -201,30 +201,13 @@
"properties": [
{ "name": "description", "type": "string", "optional": true, "description": "String label of this stack trace. For async traces this may be a name of the function that initiated the async call." },
{ "name": "callFrames", "type": "array", "items": { "$ref": "CallFrame" }, "description": "JavaScript function name." },
{ "name": "parent", "$ref": "StackTrace", "optional": true, "description": "Asynchronous JavaScript stack trace that preceded this stack, if available." },
{ "name": "parentId", "$ref": "StackTraceId", "optional": true, "experimental": true, "description": "Asynchronous JavaScript stack trace that preceded this stack, if available." }
{ "name": "parent", "$ref": "StackTrace", "optional": true, "description": "Asynchronous JavaScript stack trace that preceded this stack, if available." }
]
},
{
"id": "AsyncTaskId",
"type": "string",
"experimental": true
},
{
"id": "UniqueDebuggerId",
"type": "string",
"description": "Unique identifier of current debugger.",
"experimental": true
},
{
"id": "StackTraceId",
"type": "object",
"description": "External stack trace comes from another debugger and can be resolved there. This allows to track cross-debugger calls. See <code>Runtime.StackTrace</code> and <code>Debugger.paused</code> for usages.",
"properties": [
{ "name": "id", "type": "string" },
{ "name": "debuggerId", "$ref": "UniqueDebuggerId" }
],
"experimental": true
}
],
"commands": [
......@@ -533,9 +516,6 @@
"commands": [
{
"name": "enable",
"returns": [
{ "name": "debuggerId", "$ref": "Runtime.UniqueDebuggerId", "experimental": true, "description": "Unique identifier of the debugger." }
],
"description": "Enables debugger for the given page. Clients should not assume that the debugging has been enabled until the result for this command is received."
},
{
......@@ -647,17 +627,6 @@
"name": "resume",
"description": "Resumes JavaScript execution."
},
{
"name": "getStackTrace",
"parameters": [
{ "name": "stackTraceId", "$ref": "Runtime.StackTraceId" }
],
"returns": [
{ "name": "stackTrace", "$ref": "Runtime.StackTrace" }
],
"description": "Returns stack trace with given <code>stackTraceId</code>.",
"experimental": true
},
{
"name": "searchInContent",
"parameters": [
......@@ -683,7 +652,6 @@
{ "name": "callFrames", "type": "array", "optional": true, "items": { "$ref": "CallFrame" }, "description": "New stack trace in case editing has happened while VM was stopped." },
{ "name": "stackChanged", "type": "boolean", "optional": true, "description": "Whether current call stack was modified after applying the changes." },
{ "name": "asyncStackTrace", "$ref": "Runtime.StackTrace", "optional": true, "description": "Async stack trace, if any." },
{ "name": "asyncStackTraceId", "$ref": "Runtime.StackTraceId", "optional": true, "experimental": true, "description": "Async stack trace, if any." },
{ "name": "exceptionDetails", "optional": true, "$ref": "Runtime.ExceptionDetails", "description": "Exception details if any." }
],
"description": "Edits JavaScript source live."
......@@ -695,8 +663,7 @@
],
"returns": [
{ "name": "callFrames", "type": "array", "items": { "$ref": "CallFrame" }, "description": "New stack trace." },
{ "name": "asyncStackTrace", "$ref": "Runtime.StackTrace", "optional": true, "description": "Async stack trace, if any." },
{ "name": "asyncStackTraceId", "$ref": "Runtime.StackTraceId", "optional": true, "experimental": true, "description": "Async stack trace, if any." }
{ "name": "asyncStackTrace", "$ref": "Runtime.StackTrace", "optional": true, "description": "Async stack trace, if any." }
],
"description": "Restarts particular call frame from the beginning."
},
......@@ -836,7 +803,6 @@
{ "name": "data", "type": "object", "optional": true, "description": "Object containing break-specific auxiliary properties." },
{ "name": "hitBreakpoints", "type": "array", "optional": true, "items": { "type": "string" }, "description": "Hit breakpoints IDs" },
{ "name": "asyncStackTrace", "$ref": "Runtime.StackTrace", "optional": true, "description": "Async stack trace, if any." },
{ "name": "asyncStackTraceId", "$ref": "Runtime.StackTraceId", "optional": true, "experimental": true, "description": "Async stack trace, if any." },
{ "name": "scheduledAsyncTaskId", "$ref": "Runtime.AsyncTaskId", "optional": true, "experimental": true, "description": "Scheduled async task id." }
],
"description": "Fired when the virtual machine stopped on breakpoint or exception or any other stop criteria."
......
......@@ -4,7 +4,6 @@
#include "src/inspector/string-util.h"
#include "src/base/platform/platform.h"
#include "src/conversions.h"
#include "src/inspector/protocol/Protocol.h"
#include "src/unicode-cache.h"
......@@ -152,19 +151,4 @@ StringBufferImpl::StringBufferImpl(String16& string) {
m_string = toStringView(m_owner);
}
String16 debuggerIdToString(const std::pair<int64_t, int64_t>& debuggerId) {
const size_t kBufferSize = 35;
char buffer[kBufferSize];
v8::base::OS::SNPrintF(buffer, kBufferSize, "(%08" PRIX64 "%08" PRIX64 ")",
debuggerId.first, debuggerId.second);
return String16(buffer);
}
String16 stackTraceIdToString(uintptr_t id) {
String16Builder builder;
builder.appendNumber(reinterpret_cast<size_t>(id));
return builder.toString();
}
} // namespace v8_inspector
......@@ -87,9 +87,6 @@ class StringBufferImpl : public StringBuffer {
DISALLOW_COPY_AND_ASSIGN(StringBufferImpl);
};
String16 debuggerIdToString(const std::pair<int64_t, int64_t>& debuggerId);
String16 stackTraceIdToString(uintptr_t id);
} // namespace v8_inspector
#endif // V8_INSPECTOR_STRINGUTIL_H_
......@@ -370,9 +370,7 @@ void V8DebuggerAgentImpl::enableImpl() {
}
}
Response V8DebuggerAgentImpl::enable(String16* outDebuggerId) {
*outDebuggerId = debuggerIdToString(
m_debugger->debuggerIdFor(m_session->contextGroupId()));
Response V8DebuggerAgentImpl::enable() {
if (enabled()) return Response::OK();
if (!m_inspector->client()->canExecuteScripts(m_session->contextGroupId()))
......@@ -717,27 +715,6 @@ Response V8DebuggerAgentImpl::continueToLocation(
protocol::Debugger::ContinueToLocation::TargetCallFramesEnum::Any));
}
Response V8DebuggerAgentImpl::getStackTrace(
std::unique_ptr<protocol::Runtime::StackTraceId> inStackTraceId,
std::unique_ptr<protocol::Runtime::StackTrace>* outStackTrace) {
bool isOk = false;
int64_t id = inStackTraceId->getId().toInteger64(&isOk);
std::pair<int64_t, int64_t> debuggerId =
m_debugger->debuggerIdFor(inStackTraceId->getDebuggerId());
V8StackTraceId v8StackTraceId(id, debuggerId);
if (!isOk || v8StackTraceId.IsInvalid()) {
return Response::Error("Invalid stack trace id");
}
auto stack =
m_debugger->stackTraceFor(m_session->contextGroupId(), v8StackTraceId);
if (!stack) {
return Response::Error("Stack trace with given id is not found");
}
*outStackTrace =
stack->buildInspectorObject(m_debugger->maxAsyncCallChainDepth());
return Response::OK();
}
bool V8DebuggerAgentImpl::isFunctionBlackboxed(const String16& scriptId,
const v8::debug::Location& start,
const v8::debug::Location& end) {
......@@ -839,7 +816,6 @@ Response V8DebuggerAgentImpl::setScriptSource(
Maybe<protocol::Array<protocol::Debugger::CallFrame>>* newCallFrames,
Maybe<bool>* stackChanged,
Maybe<protocol::Runtime::StackTrace>* asyncStackTrace,
Maybe<protocol::Runtime::StackTraceId>* asyncStackTraceId,
Maybe<protocol::Runtime::ExceptionDetails>* optOutCompileError) {
if (!enabled()) return Response::Error(kDebuggerNotEnabled);
......@@ -882,15 +858,13 @@ Response V8DebuggerAgentImpl::setScriptSource(
if (!response.isSuccess()) return response;
*newCallFrames = std::move(callFrames);
*asyncStackTrace = currentAsyncStackTrace();
*asyncStackTraceId = currentExternalStackTrace();
return Response::OK();
}
Response V8DebuggerAgentImpl::restartFrame(
const String16& callFrameId,
std::unique_ptr<Array<CallFrame>>* newCallFrames,
Maybe<protocol::Runtime::StackTrace>* asyncStackTrace,
Maybe<protocol::Runtime::StackTraceId>* asyncStackTraceId) {
Maybe<protocol::Runtime::StackTrace>* asyncStackTrace) {
if (!isPaused()) return Response::Error(kDebuggerNotPaused);
InjectedScript::CallFrameScope scope(m_session, callFrameId);
Response response = scope.initialize();
......@@ -906,7 +880,6 @@ Response V8DebuggerAgentImpl::restartFrame(
response = currentCallFrames(newCallFrames);
if (!response.isSuccess()) return response;
*asyncStackTrace = currentAsyncStackTrace();
*asyncStackTraceId = currentExternalStackTrace();
return Response::OK();
}
......@@ -1314,16 +1287,6 @@ V8DebuggerAgentImpl::currentAsyncStackTrace() {
m_debugger->maxAsyncCallChainDepth() - 1);
}
std::unique_ptr<protocol::Runtime::StackTraceId>
V8DebuggerAgentImpl::currentExternalStackTrace() {
V8StackTraceId externalParent = m_debugger->currentExternalParent();
if (externalParent.IsInvalid()) return nullptr;
return protocol::Runtime::StackTraceId::create()
.setId(stackTraceIdToString(externalParent.id))
.setDebuggerId(debuggerIdToString(externalParent.debugger_id))
.build();
}
bool V8DebuggerAgentImpl::isPaused() const {
return m_debugger->isPausedInContextGroup(m_session->contextGroupId());
}
......@@ -1535,8 +1498,7 @@ void V8DebuggerAgentImpl::didPause(
m_frontend.paused(std::move(protocolCallFrames), breakReason,
std::move(breakAuxData), std::move(hitBreakpointIds),
currentAsyncStackTrace(), currentExternalStackTrace(),
std::move(scheduledAsyncTaskId));
currentAsyncStackTrace(), std::move(scheduledAsyncTaskId));
}
void V8DebuggerAgentImpl::didContinue() {
......
......@@ -39,7 +39,7 @@ class V8DebuggerAgentImpl : public protocol::Debugger::Backend {
void restore();
// Part of the protocol.
Response enable(String16* outDebuggerId) override;
Response enable() override;
Response disable() override;
Response setBreakpointsActive(bool active) override;
Response setSkipAllPauses(bool skip) override;
......@@ -57,9 +57,6 @@ class V8DebuggerAgentImpl : public protocol::Debugger::Backend {
Response removeBreakpoint(const String16& breakpointId) override;
Response continueToLocation(std::unique_ptr<protocol::Debugger::Location>,
Maybe<String16> targetCallFrames) override;
Response getStackTrace(
std::unique_ptr<protocol::Runtime::StackTraceId> inStackTraceId,
std::unique_ptr<protocol::Runtime::StackTrace>* outStackTrace) override;
Response searchInContent(
const String16& scriptId, const String16& query,
Maybe<bool> optionalCaseSensitive, Maybe<bool> optionalIsRegex,
......@@ -76,14 +73,12 @@ class V8DebuggerAgentImpl : public protocol::Debugger::Backend {
Maybe<protocol::Array<protocol::Debugger::CallFrame>>* optOutCallFrames,
Maybe<bool>* optOutStackChanged,
Maybe<protocol::Runtime::StackTrace>* optOutAsyncStackTrace,
Maybe<protocol::Runtime::StackTraceId>* optOutAsyncStackTraceId,
Maybe<protocol::Runtime::ExceptionDetails>* optOutCompileError) override;
Response restartFrame(
const String16& callFrameId,
std::unique_ptr<protocol::Array<protocol::Debugger::CallFrame>>*
newCallFrames,
Maybe<protocol::Runtime::StackTrace>* asyncStackTrace,
Maybe<protocol::Runtime::StackTraceId>* asyncStackTraceId) override;
Maybe<protocol::Runtime::StackTrace>* asyncStackTrace) override;
Response getScriptSource(const String16& scriptId,
String16* scriptSource) override;
Response pause() override;
......@@ -154,7 +149,6 @@ class V8DebuggerAgentImpl : public protocol::Debugger::Backend {
Response currentCallFrames(
std::unique_ptr<protocol::Array<protocol::Debugger::CallFrame>>*);
std::unique_ptr<protocol::Runtime::StackTrace> currentAsyncStackTrace();
std::unique_ptr<protocol::Runtime::StackTraceId> currentExternalStackTrace();
void setPauseOnExceptionsImpl(int);
......
......@@ -562,11 +562,6 @@ std::shared_ptr<AsyncStackTrace> V8Debugger::currentAsyncParent() {
return m_currentAsyncParent.empty() ? nullptr : m_currentAsyncParent.back();
}
V8StackTraceId V8Debugger::currentExternalParent() {
return m_currentExternalParent.empty() ? V8StackTraceId()
: m_currentExternalParent.back();
}
v8::MaybeLocal<v8::Value> V8Debugger::getTargetScopes(
v8::Local<v8::Context> context, v8::Local<v8::Value> value,
ScopeTargetKind kind) {
......@@ -731,51 +726,6 @@ void V8Debugger::setAsyncCallStackDepth(V8DebuggerAgentImpl* agent, int depth) {
if (!maxAsyncCallStackDepth) allAsyncTasksCanceled();
}
std::shared_ptr<AsyncStackTrace> V8Debugger::stackTraceFor(
int contextGroupId, const V8StackTraceId& id) {
if (debuggerIdFor(contextGroupId) != id.debugger_id) return nullptr;
auto it = m_storedStackTraces.find(id.id);
if (it == m_storedStackTraces.end()) return nullptr;
return it->second.lock();
}
V8StackTraceId V8Debugger::storeCurrentStackTrace(
const StringView& description) {
if (!m_maxAsyncCallStackDepth) return V8StackTraceId();
v8::HandleScope scope(m_isolate);
int contextGroupId = currentContextGroupId();
if (!contextGroupId) return V8StackTraceId();
std::shared_ptr<AsyncStackTrace> asyncStack =
AsyncStackTrace::capture(this, contextGroupId, toString16(description),
V8StackTraceImpl::maxCallStackSizeToCapture);
if (!asyncStack) return V8StackTraceId();
uintptr_t id = ++m_lastStackTraceId;
m_storedStackTraces[id] = asyncStack;
m_allAsyncStacks.push_back(std::move(asyncStack));
++m_asyncStacksCount;
collectOldAsyncStacksIfNeeded();
return V8StackTraceId(id, debuggerIdFor(contextGroupId));
}
void V8Debugger::externalAsyncTaskStarted(const V8StackTraceId& parent) {
if (!m_maxAsyncCallStackDepth || parent.IsInvalid()) return;
m_currentExternalParent.push_back(parent);
m_currentAsyncParent.emplace_back();
m_currentTasks.push_back(reinterpret_cast<void*>(parent.id));
}
void V8Debugger::externalAsyncTaskFinished(const V8StackTraceId& parent) {
if (!m_maxAsyncCallStackDepth || m_currentExternalParent.empty()) return;
m_currentExternalParent.pop_back();
m_currentAsyncParent.pop_back();
DCHECK(m_currentTasks.back() == reinterpret_cast<void*>(parent.id));
m_currentTasks.pop_back();
}
void V8Debugger::asyncTaskScheduled(const StringView& taskName, void* task,
bool recurring) {
asyncTaskScheduledForStack(toString16(taskName), task, recurring);
......@@ -835,7 +785,6 @@ void V8Debugger::asyncTaskStartedForStack(void* task) {
} else {
m_currentAsyncParent.emplace_back();
}
m_currentExternalParent.emplace_back();
}
void V8Debugger::asyncTaskFinishedForStack(void* task) {
......@@ -846,7 +795,6 @@ void V8Debugger::asyncTaskFinishedForStack(void* task) {
m_currentTasks.pop_back();
m_currentAsyncParent.pop_back();
m_currentExternalParent.pop_back();
if (m_recurringTasks.find(task) == m_recurringTasks.end()) {
asyncTaskCanceledForStack(task);
......@@ -893,7 +841,6 @@ void V8Debugger::allAsyncTasksCanceled() {
m_asyncTaskStacks.clear();
m_recurringTasks.clear();
m_currentAsyncParent.clear();
m_currentExternalParent.clear();
m_currentTasks.clear();
m_framesCache.clear();
......@@ -945,7 +892,6 @@ void V8Debugger::collectOldAsyncStacksIfNeeded() {
--m_asyncStacksCount;
}
cleanupExpiredWeakPointers(m_asyncTaskStacks);
cleanupExpiredWeakPointers(m_storedStackTraces);
for (auto it = m_recurringTasks.begin(); it != m_recurringTasks.end();) {
if (m_asyncTaskStacks.find(*it) == m_asyncTaskStacks.end()) {
it = m_recurringTasks.erase(it);
......@@ -981,26 +927,6 @@ void V8Debugger::setMaxAsyncTaskStacksForTest(int limit) {
m_maxAsyncCallStacks = limit;
}
std::pair<int64_t, int64_t> V8Debugger::debuggerIdFor(int contextGroupId) {
auto it = m_contextGroupIdToDebuggerId.find(contextGroupId);
if (it != m_contextGroupIdToDebuggerId.end()) return it->second;
std::pair<int64_t, int64_t> debuggerId(
v8::debug::GetNextRandomInt64(m_isolate),
v8::debug::GetNextRandomInt64(m_isolate));
m_contextGroupIdToDebuggerId.insert(
it, std::make_pair(contextGroupId, debuggerId));
m_serializedDebuggerIdToDebuggerId.insert(
std::make_pair(debuggerIdToString(debuggerId), debuggerId));
return debuggerId;
}
std::pair<int64_t, int64_t> V8Debugger::debuggerIdFor(
const String16& serializedDebuggerId) {
auto it = m_serializedDebuggerIdToDebuggerId.find(serializedDebuggerId);
if (it != m_serializedDebuggerIdToDebuggerId.end()) return it->second;
return std::make_pair(0, 0);
}
void V8Debugger::dumpAsyncTaskStacksStateForTest() {
fprintf(stdout, "Async stacks count: %d\n", m_asyncStacksCount);
fprintf(stdout, "Scheduled async tasks: %zu\n", m_asyncTaskStacks.size());
......
......@@ -27,7 +27,6 @@ class V8Debugger;
class V8DebuggerAgentImpl;
class V8InspectorImpl;
class V8StackTraceImpl;
struct V8StackTraceId;
using protocol::Response;
using ScheduleStepIntoAsyncCallback =
......@@ -80,7 +79,6 @@ class V8Debugger : public v8::debug::DebugDelegate {
void setAsyncCallStackDepth(V8DebuggerAgentImpl*, int);
std::shared_ptr<AsyncStackTrace> currentAsyncParent();
V8StackTraceId currentExternalParent();
std::shared_ptr<StackFrame> symbolize(v8::Local<v8::StackFrame> v8Frame);
......@@ -100,10 +98,6 @@ class V8Debugger : public v8::debug::DebugDelegate {
void asyncTaskFinished(void* task);
void allAsyncTasksCanceled();
V8StackTraceId storeCurrentStackTrace(const StringView& description);
void externalAsyncTaskStarted(const V8StackTraceId& parent);
void externalAsyncTaskFinished(const V8StackTraceId& parent);
void muteScriptParsedEvents();
void unmuteScriptParsedEvents();
......@@ -116,12 +110,6 @@ class V8Debugger : public v8::debug::DebugDelegate {
void* scheduledAsyncTask() { return m_scheduledAsyncTask; }
std::pair<int64_t, int64_t> debuggerIdFor(int contextGroupId);
std::pair<int64_t, int64_t> debuggerIdFor(
const String16& serializedDebuggerId);
std::shared_ptr<AsyncStackTrace> stackTraceFor(int contextGroupId,
const V8StackTraceId& id);
private:
void clearContinueToLocation();
bool shouldContinueToCurrentLocation();
......@@ -198,7 +186,6 @@ class V8Debugger : public v8::debug::DebugDelegate {
std::vector<void*> m_currentTasks;
std::vector<std::shared_ptr<AsyncStackTrace>> m_currentAsyncParent;
std::vector<V8StackTraceId> m_currentExternalParent;
void collectOldAsyncStacksIfNeeded();
int m_asyncStacksCount = 0;
......@@ -217,16 +204,6 @@ class V8Debugger : public v8::debug::DebugDelegate {
bool m_pauseOnAsyncCall = false;
void* m_scheduledAsyncTask = nullptr;
using StackTraceIdToStackTrace =
protocol::HashMap<uintptr_t, std::weak_ptr<AsyncStackTrace>>;
StackTraceIdToStackTrace m_storedStackTraces;
uintptr_t m_lastStackTraceId = 0;
protocol::HashMap<int, std::pair<int64_t, int64_t>>
m_contextGroupIdToDebuggerId;
protocol::HashMap<String16, std::pair<int64_t, int64_t>>
m_serializedDebuggerIdToDebuggerId;
WasmTranslation m_wasmTranslation;
DISALLOW_COPY_AND_ASSIGN(V8Debugger);
......
......@@ -287,19 +287,6 @@ std::unique_ptr<V8StackTrace> V8InspectorImpl::captureStackTrace(
return m_debugger->captureStackTrace(fullStack);
}
V8StackTraceId V8InspectorImpl::storeCurrentStackTrace(
const StringView& description) {
return m_debugger->storeCurrentStackTrace(description);
}
void V8InspectorImpl::externalAsyncTaskStarted(const V8StackTraceId& parent) {
m_debugger->externalAsyncTaskStarted(parent);
}
void V8InspectorImpl::externalAsyncTaskFinished(const V8StackTraceId& parent) {
m_debugger->externalAsyncTaskFinished(parent);
}
void V8InspectorImpl::asyncTaskScheduled(const StringView& taskName, void* task,
bool recurring) {
if (!task) return;
......
......@@ -97,10 +97,6 @@ class V8InspectorImpl : public V8Inspector {
void asyncTaskFinished(void* task) override;
void allAsyncTasksCanceled() override;
V8StackTraceId storeCurrentStackTrace(const StringView& description) override;
void externalAsyncTaskStarted(const V8StackTraceId& parent) override;
void externalAsyncTaskFinished(const V8StackTraceId& parent) override;
unsigned nextExceptionId() { return ++m_lastExceptionId; }
void enableStackCapturingIfNeeded();
void disableStackCapturingIfNeeded();
......
......@@ -32,10 +32,8 @@ std::vector<std::shared_ptr<StackFrame>> toFramesVector(
void calculateAsyncChain(V8Debugger* debugger, int contextGroupId,
std::shared_ptr<AsyncStackTrace>* asyncParent,
V8StackTraceId* externalParent, int* maxAsyncDepth) {
int* maxAsyncDepth) {
*asyncParent = debugger->currentAsyncParent();
*externalParent = debugger->currentExternalParent();
DCHECK(externalParent->IsInvalid() || !*asyncParent);
if (maxAsyncDepth) *maxAsyncDepth = debugger->maxAsyncCallChainDepth();
// Do not accidentally append async call chain from another group. This should
......@@ -44,7 +42,6 @@ void calculateAsyncChain(V8Debugger* debugger, int contextGroupId,
if (contextGroupId && *asyncParent &&
(*asyncParent)->contextGroupId() != contextGroupId) {
asyncParent->reset();
*externalParent = V8StackTraceId();
if (maxAsyncDepth) *maxAsyncDepth = 0;
return;
}
......@@ -59,8 +56,7 @@ void calculateAsyncChain(V8Debugger* debugger, int contextGroupId,
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 V8StackTraceId& externalParent, int maxAsyncDepth) {
const std::shared_ptr<AsyncStackTrace>& asyncParent, int maxAsyncDepth) {
if (asyncParent && frames.empty() &&
description == asyncParent->description()) {
return asyncParent->buildInspectorObject(maxAsyncDepth);
......@@ -79,26 +75,11 @@ std::unique_ptr<protocol::Runtime::StackTrace> buildInspectorObjectCommon(
if (asyncParent && maxAsyncDepth > 0) {
stackTrace->setParent(asyncParent->buildInspectorObject(maxAsyncDepth - 1));
}
if (!externalParent.IsInvalid() && maxAsyncDepth > 0) {
stackTrace->setParentId(
protocol::Runtime::StackTraceId::create()
.setId(stackTraceIdToString(externalParent.id))
.setDebuggerId(debuggerIdToString(externalParent.debugger_id))
.build());
}
return stackTrace;
}
} // namespace
V8StackTraceId::V8StackTraceId() : id(0), debugger_id(std::make_pair(0, 0)) {}
V8StackTraceId::V8StackTraceId(uintptr_t id,
const std::pair<int64_t, int64_t> debugger_id)
: id(id), debugger_id(debugger_id) {}
bool V8StackTraceId::IsInvalid() const { return !id; }
StackFrame::StackFrame(v8::Local<v8::StackFrame> v8Frame)
: m_functionName(toProtocolString(v8Frame->GetFunctionName())),
m_scriptId(String16::fromInteger(v8Frame->GetScriptId())),
......@@ -164,13 +145,10 @@ std::unique_ptr<V8StackTraceImpl> V8StackTraceImpl::create(
int maxAsyncDepth = 0;
std::shared_ptr<AsyncStackTrace> asyncParent;
V8StackTraceId externalParent;
calculateAsyncChain(debugger, contextGroupId, &asyncParent, &externalParent,
&maxAsyncDepth);
if (frames.empty() && !asyncParent && externalParent.IsInvalid())
return nullptr;
return std::unique_ptr<V8StackTraceImpl>(new V8StackTraceImpl(
std::move(frames), maxAsyncDepth, asyncParent, externalParent));
calculateAsyncChain(debugger, contextGroupId, &asyncParent, &maxAsyncDepth);
if (frames.empty() && !asyncParent) return nullptr;
return std::unique_ptr<V8StackTraceImpl>(
new V8StackTraceImpl(std::move(frames), maxAsyncDepth, asyncParent));
}
// static
......@@ -190,18 +168,16 @@ std::unique_ptr<V8StackTraceImpl> V8StackTraceImpl::capture(
V8StackTraceImpl::V8StackTraceImpl(
std::vector<std::shared_ptr<StackFrame>> frames, int maxAsyncDepth,
std::shared_ptr<AsyncStackTrace> asyncParent,
const V8StackTraceId& externalParent)
std::shared_ptr<AsyncStackTrace> asyncParent)
: m_frames(std::move(frames)),
m_maxAsyncDepth(maxAsyncDepth),
m_asyncParent(asyncParent),
m_externalParent(externalParent) {}
m_asyncParent(asyncParent) {}
V8StackTraceImpl::~V8StackTraceImpl() {}
std::unique_ptr<V8StackTrace> V8StackTraceImpl::clone() {
return std::unique_ptr<V8StackTrace>(new V8StackTraceImpl(
m_frames, 0, std::shared_ptr<AsyncStackTrace>(), V8StackTraceId()));
return std::unique_ptr<V8StackTrace>(
new V8StackTraceImpl(m_frames, 0, std::shared_ptr<AsyncStackTrace>()));
}
bool V8StackTraceImpl::isEmpty() const { return m_frames.empty(); }
......@@ -229,7 +205,7 @@ StringView V8StackTraceImpl::topFunctionName() const {
std::unique_ptr<protocol::Runtime::StackTrace>
V8StackTraceImpl::buildInspectorObjectImpl() const {
return buildInspectorObjectCommon(m_frames, String16(), m_asyncParent.lock(),
m_externalParent, m_maxAsyncDepth);
m_maxAsyncDepth);
}
std::unique_ptr<protocol::Runtime::API::StackTrace>
......@@ -316,12 +292,9 @@ std::shared_ptr<AsyncStackTrace> AsyncStackTrace::capture(
}
std::shared_ptr<AsyncStackTrace> asyncParent;
V8StackTraceId externalParent;
calculateAsyncChain(debugger, contextGroupId, &asyncParent, &externalParent,
nullptr);
calculateAsyncChain(debugger, contextGroupId, &asyncParent, nullptr);
if (frames.empty() && !asyncParent && externalParent.IsInvalid())
return nullptr;
if (frames.empty() && !asyncParent) return nullptr;
// When async call chain is empty but doesn't contain useful schedule stack
// but doesn't synchronous we can merge them together. e.g. Promise
......@@ -335,29 +308,25 @@ std::shared_ptr<AsyncStackTrace> AsyncStackTrace::capture(
if (!contextGroupId && asyncParent) {
contextGroupId = asyncParent->m_contextGroupId;
}
return std::shared_ptr<AsyncStackTrace>(
new AsyncStackTrace(contextGroupId, description, std::move(frames),
asyncParent, externalParent));
return std::shared_ptr<AsyncStackTrace>(new AsyncStackTrace(
contextGroupId, description, std::move(frames), asyncParent));
}
AsyncStackTrace::AsyncStackTrace(
int contextGroupId, const String16& description,
std::vector<std::shared_ptr<StackFrame>> frames,
std::shared_ptr<AsyncStackTrace> asyncParent,
const V8StackTraceId& externalParent)
std::shared_ptr<AsyncStackTrace> asyncParent)
: m_contextGroupId(contextGroupId),
m_description(description),
m_frames(std::move(frames)),
m_asyncParent(asyncParent),
m_externalParent(externalParent) {
m_asyncParent(asyncParent) {
DCHECK(m_contextGroupId);
}
std::unique_ptr<protocol::Runtime::StackTrace>
AsyncStackTrace::buildInspectorObject(int maxAsyncDepth) const {
return buildInspectorObjectCommon(m_frames, m_description,
m_asyncParent.lock(), m_externalParent,
maxAsyncDepth);
m_asyncParent.lock(), maxAsyncDepth);
}
int AsyncStackTrace::contextGroupId() const { return m_contextGroupId; }
......
......@@ -19,7 +19,6 @@ namespace v8_inspector {
class AsyncStackTrace;
class V8Debugger;
class WasmTranslation;
struct V8StackTraceId;
class StackFrame {
public:
......@@ -79,8 +78,7 @@ class V8StackTraceImpl : public V8StackTrace {
private:
V8StackTraceImpl(std::vector<std::shared_ptr<StackFrame>> frames,
int maxAsyncDepth,
std::shared_ptr<AsyncStackTrace> asyncParent,
const V8StackTraceId& externalParent);
std::shared_ptr<AsyncStackTrace> asyncParent);
class StackFrameIterator {
public:
......@@ -99,7 +97,6 @@ class V8StackTraceImpl : public V8StackTrace {
std::vector<std::shared_ptr<StackFrame>> m_frames;
int m_maxAsyncDepth;
std::weak_ptr<AsyncStackTrace> m_asyncParent;
V8StackTraceId m_externalParent;
DISALLOW_COPY_AND_ASSIGN(V8StackTraceImpl);
};
......@@ -126,15 +123,13 @@ class AsyncStackTrace {
private:
AsyncStackTrace(int contextGroupId, const String16& description,
std::vector<std::shared_ptr<StackFrame>> frames,
std::shared_ptr<AsyncStackTrace> asyncParent,
const V8StackTraceId& externalParent);
std::shared_ptr<AsyncStackTrace> asyncParent);
int m_contextGroupId;
String16 m_description;
std::vector<std::shared_ptr<StackFrame>> m_frames;
std::weak_ptr<AsyncStackTrace> m_asyncParent;
V8StackTraceId m_externalParent;
DISALLOW_COPY_AND_ASSIGN(AsyncStackTrace);
};
......
Tests external stack traces
Running test: testDebuggerId
Enabling debugger first time..
Enabling debugger again..
> second Debugger.enable returns the same debugger id
Enabling debugger in another context group..
> Debugger.enable in another context group returns own debugger id
Running test: testInstrumentation
{
id : <messageId>
result : {
stackTrace : {
callFrames : [
[0] : {
columnNumber : 15
functionName :
lineNumber : 0
scriptId : <scriptId>
url :
}
]
description : stack
}
}
}
Running test: testDisableStacksAfterStored
> external async stack trace is empty
Running test: testDisableStacksAfterStarted
> external async stack trace is empty
Running test: testExternalStacks
(anonymous) (expr1-2.js:1:6)
-- stack2 --
store (utils.js:2:25)
(anonymous) (expr2.js:1:11)
-- stack --
store (utils.js:2:25)
(anonymous) (expr1-1.js:0:0)
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
InspectorTest.log('Tests external stack traces');
let contextGroup1 = new InspectorTest.ContextGroup();
let session1 = contextGroup1.connect();
let Protocol1 = session1.Protocol;
let contextGroup2 = new InspectorTest.ContextGroup();
let session2 = contextGroup2.connect();
let Protocol2 = session2.Protocol;
let utilsScript = `
function store(description) {
let buffer = inspector.storeCurrentStackTrace(description);
return '[' + new Int32Array(buffer).join(',') + ']';
}
function started(id) {
inspector.externalAsyncTaskStarted(Int32Array.from(JSON.parse(id)).buffer);
}
function finished(id) {
inspector.externalAsyncTaskFinished(Int32Array.from(JSON.parse(id)).buffer);
}
//# sourceURL=utils.js`;
contextGroup1.addScript(utilsScript);
contextGroup2.addScript(utilsScript);
InspectorTest.runAsyncTestSuite([
async function testDebuggerId() {
InspectorTest.log('Enabling debugger first time..');
let {result: {debuggerId}} = await Protocol1.Debugger.enable();
let firstDebuggerId = debuggerId;
InspectorTest.log('Enabling debugger again..');
({result: {debuggerId}} = await Protocol1.Debugger.enable());
if (firstDebuggerId !== debuggerId) {
InspectorTest.log(
'FAIL: second Debugger.enable returns different debugger id');
} else {
InspectorTest.log(
'> second Debugger.enable returns the same debugger id');
}
InspectorTest.log('Enabling debugger in another context group..');
({result: {debuggerId}} = await Protocol2.Debugger.enable());
if (firstDebuggerId === debuggerId) {
InspectorTest.log(
'FAIL: Debugger.enable in another context group returns the same debugger id');
} else {
InspectorTest.log(
'> Debugger.enable in another context group returns own debugger id');
}
},
async function testInstrumentation() {
Protocol1.Debugger.enable();
Protocol1.Debugger.setAsyncCallStackDepth({maxDepth: 32});
let result = await Protocol1.Runtime.evaluate(
{expression: 'id = inspector.storeCurrentStackTrace(\'stack\')'});
let stackTraceId = result.result.result.objectId;
Protocol1.Runtime.evaluate({
expression: `inspector.externalAsyncTaskStarted(id);
debugger;
inspector.externalAsyncTaskFinished(id);`
});
let {params: {callFrames, asyncStackTraceId}} =
await Protocol1.Debugger.oncePaused();
result = await Protocol1.Debugger.getStackTrace(
{stackTraceId: asyncStackTraceId});
InspectorTest.logMessage(result);
await Protocol1.Debugger.disable();
},
async function testDisableStacksAfterStored() {
Protocol1.Debugger.enable();
Protocol1.Debugger.setAsyncCallStackDepth({maxDepth: 32});
let result = await Protocol1.Runtime.evaluate(
{expression: 'id = inspector.storeCurrentStackTrace(\'stack\')'});
let stackTraceId = result.result.result.objectId;
Protocol1.Debugger.setAsyncCallStackDepth({maxDepth: 0});
Protocol1.Runtime.evaluate({
expression: `inspector.externalAsyncTaskStarted(id);
debugger;
inspector.externalAsyncTaskFinished(id);`
});
let {params: {callFrames, asyncStackTraceId}} =
await Protocol1.Debugger.oncePaused();
if (!asyncStackTraceId) {
InspectorTest.log('> external async stack trace is empty');
} else {
InspectorTest.log('FAIL: external async stack trace is reported');
}
await Protocol1.Debugger.disable();
},
async function testDisableStacksAfterStarted() {
Protocol1.Debugger.enable();
Protocol1.Debugger.setAsyncCallStackDepth({maxDepth: 32});
let result = await Protocol1.Runtime.evaluate(
{expression: 'id = inspector.storeCurrentStackTrace(\'stack\')'});
let stackTraceId = result.result.result.objectId;
Protocol1.Runtime.evaluate(
{expression: 'inspector.externalAsyncTaskStarted(id);'});
Protocol1.Debugger.setAsyncCallStackDepth({maxDepth: 0});
Protocol1.Runtime.evaluate({
expression: `debugger;
inspector.externalAsyncTaskFinished(id);`
});
let {params: {callFrames, asyncStackTraceId}} =
await Protocol1.Debugger.oncePaused();
if (!asyncStackTraceId) {
InspectorTest.log('> external async stack trace is empty');
} else {
InspectorTest.log('FAIL: external async stack trace is reported');
}
await Protocol1.Debugger.disable();
},
async function testExternalStacks() {
let debuggerId1 = (await Protocol1.Debugger.enable()).result.debuggerId;
let debuggerId2 = (await Protocol2.Debugger.enable()).result.debuggerId;
Protocol1.Debugger.setAsyncCallStackDepth({maxDepth: 32});
Protocol2.Debugger.setAsyncCallStackDepth({maxDepth: 32});
let stackTraceId1 = (await Protocol1.Runtime.evaluate({
expression: 'store(\'stack\')//# sourceURL=expr1-1.js'
})).result.result.value;
let stackTraceId2 = (await Protocol2.Runtime.evaluate({
expression: `started('${stackTraceId1}');
id = store('stack2');
finished('${stackTraceId1}');
id
//# sourceURL=expr2.js`
})).result.result.value;
Protocol1.Runtime.evaluate({
expression: `started('${stackTraceId2}');
debugger;
finished('${stackTraceId2}');
id
//# sourceURL=expr1-2.js`
});
let {params: {callFrames, asyncStackTraceId}} =
await Protocol1.Debugger.oncePaused();
let debuggers = new Map(
[[debuggerId1, Protocol1.Debugger], [debuggerId2, Protocol2.Debugger]]);
let sessions = new Map([[debuggerId1, session1], [debuggerId2, session2]]);
let currentDebuggerId = debuggerId1;
while (true) {
sessions.get(currentDebuggerId).logCallFrames(callFrames);
if (asyncStackTraceId) {
currentDebuggerId = asyncStackTraceId.debuggerId;
let {result: {stackTrace}} =
await debuggers.get(currentDebuggerId).getStackTrace({
stackTraceId: asyncStackTraceId
});
InspectorTest.log(`-- ${stackTrace.description} --`);
callFrames = stackTrace.callFrames;
asyncStackTraceId = stackTrace.parentId;
} else {
break;
}
}
Protocol1.Debugger.disable();
await Protocol2.Debugger.disable();
}
]);
......@@ -693,16 +693,6 @@ class InspectorExtension : public IsolateData::SetupGlobalTask {
inspector->Set(ToV8String(isolate, "createObjectWithAccessor"),
v8::FunctionTemplate::New(
isolate, &InspectorExtension::CreateObjectWithAccessor));
inspector->Set(ToV8String(isolate, "storeCurrentStackTrace"),
v8::FunctionTemplate::New(
isolate, &InspectorExtension::StoreCurrentStackTrace));
inspector->Set(ToV8String(isolate, "externalAsyncTaskStarted"),
v8::FunctionTemplate::New(
isolate, &InspectorExtension::ExternalAsyncTaskStarted));
inspector->Set(
ToV8String(isolate, "externalAsyncTaskFinished"),
v8::FunctionTemplate::New(
isolate, &InspectorExtension::ExternalAsyncTaskFinished));
global->Set(ToV8String(isolate, "inspector"), inspector);
}
......@@ -875,57 +865,6 @@ class InspectorExtension : public IsolateData::SetupGlobalTask {
v8::Isolate* isolate = info.GetIsolate();
isolate->ThrowException(ToV8String(isolate, "Setter is called"));
}
static void StoreCurrentStackTrace(
const v8::FunctionCallbackInfo<v8::Value>& args) {
if (args.Length() != 1 || !args[0]->IsString()) {
fprintf(stderr,
"Internal error: storeCurrentStackTrace('description')\n");
Exit();
}
v8::Isolate* isolate = args.GetIsolate();
v8::Local<v8::Context> context = isolate->GetCurrentContext();
IsolateData* data = IsolateData::FromContext(context);
v8::internal::Vector<uint16_t> description =
ToVector(args[0].As<v8::String>());
v8_inspector::StringView description_view(description.start(),
description.length());
v8_inspector::V8StackTraceId id =
data->StoreCurrentStackTrace(description_view);
v8::Local<v8::ArrayBuffer> buffer =
v8::ArrayBuffer::New(isolate, sizeof(id));
*static_cast<v8_inspector::V8StackTraceId*>(buffer->GetContents().Data()) =
id;
args.GetReturnValue().Set(buffer);
}
static void ExternalAsyncTaskStarted(
const v8::FunctionCallbackInfo<v8::Value>& args) {
if (args.Length() != 1 || !args[0]->IsArrayBuffer()) {
fprintf(stderr, "Internal error: externalAsyncTaskStarted(id)\n");
Exit();
}
v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
IsolateData* data = IsolateData::FromContext(context);
v8_inspector::V8StackTraceId* id =
static_cast<v8_inspector::V8StackTraceId*>(
args[0].As<v8::ArrayBuffer>()->GetContents().Data());
data->ExternalAsyncTaskStarted(*id);
}
static void ExternalAsyncTaskFinished(
const v8::FunctionCallbackInfo<v8::Value>& args) {
if (args.Length() != 1 || !args[0]->IsArrayBuffer()) {
fprintf(stderr, "Internal error: externalAsyncTaskFinished(id)\n");
Exit();
}
v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext();
IsolateData* data = IsolateData::FromContext(context);
v8_inspector::V8StackTraceId* id =
static_cast<v8_inspector::V8StackTraceId*>(
args[0].As<v8::ArrayBuffer>()->GetContents().Data());
data->ExternalAsyncTaskFinished(*id);
}
};
} // namespace
......
......@@ -203,21 +203,6 @@ void IsolateData::AsyncTaskFinished(void* task) {
inspector_->asyncTaskFinished(task);
}
v8_inspector::V8StackTraceId IsolateData::StoreCurrentStackTrace(
const v8_inspector::StringView& description) {
return inspector_->storeCurrentStackTrace(description);
}
void IsolateData::ExternalAsyncTaskStarted(
const v8_inspector::V8StackTraceId& parent) {
inspector_->externalAsyncTaskStarted(parent);
}
void IsolateData::ExternalAsyncTaskFinished(
const v8_inspector::V8StackTraceId& parent) {
inspector_->externalAsyncTaskFinished(parent);
}
void IsolateData::AddInspectedObject(int session_id,
v8::Local<v8::Value> object) {
auto it = sessions_.find(session_id);
......
......@@ -58,12 +58,6 @@ class IsolateData : public v8_inspector::V8InspectorClient {
bool recurring);
void AsyncTaskStarted(void* task);
void AsyncTaskFinished(void* task);
v8_inspector::V8StackTraceId StoreCurrentStackTrace(
const v8_inspector::StringView& description);
void ExternalAsyncTaskStarted(const v8_inspector::V8StackTraceId& parent);
void ExternalAsyncTaskFinished(const v8_inspector::V8StackTraceId& parent);
void AddInspectedObject(int session_id, v8::Local<v8::Value> object);
// Test utilities.
......
......@@ -37,11 +37,8 @@ InspectorTest.logMessage = function(originalMessage) {
if (message.id)
message.id = "<messageId>";
const nonStableFields = new Set([
'objectId', 'scriptId', 'exceptionId', 'timestamp', 'executionContextId',
'callFrameId', 'breakpointId', 'bindRemoteObjectFunctionId',
'formatterObjectId', 'debuggerId'
]);
const nonStableFields = new Set(["objectId", "scriptId", "exceptionId", "timestamp",
"executionContextId", "callFrameId", "breakpointId", "bindRemoteObjectFunctionId", "formatterObjectId" ]);
var objects = [ message ];
while (objects.length) {
var object = objects.shift();
......
......@@ -22,7 +22,6 @@ Checks createContext().
{
id : <messageId>
result : {
debuggerId : <debuggerId>
}
}
#debugger;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment