Commit 653a9e2b authored by Alexey Kozyatinskiy's avatar Alexey Kozyatinskiy Committed by Commit Bot

[inspector] introduced universal Debugger.pauseOnAsyncCall

If protocol client needs to make step-into async call:
- pause before async call using any Debugger agent capabilities,
- call Debugger.stepInto with breakOnAsyncCall flag,
- wait for Debugger.paused event, this event will contain
  asyncCallStackTrace if async call is scheduled,
- call Debugger.pauseOnAsyncCall on each known target,
- resume execution in current debugger by Debugger.resume.

Bug: chromium:778796
Cq-Include-Trybots: master.tryserver.blink:linux_trusty_blink_rel
Change-Id: I40c56278e7b1ceafc3bf81608b8ca6716c2b3168
Reviewed-on: https://chromium-review.googlesource.com/773573
Commit-Queue: Aleksey Kozyatinskiy <kozyatinskiy@chromium.org>
Reviewed-by: 's avatarDmitry Gozman <dgozman@chromium.org>
Cr-Commit-Position: refs/heads/master@{#49594}
parent 4341749d
......@@ -205,11 +205,6 @@
{ "name": "parentId", "$ref": "StackTraceId", "optional": true, "experimental": true, "description": "Asynchronous JavaScript stack trace that preceded this stack, if available." }
]
},
{
"id": "AsyncTaskId",
"type": "string",
"experimental": true
},
{
"id": "UniqueDebuggerId",
"type": "string",
......@@ -613,9 +608,9 @@
"description": "Continues execution until specific location is reached."
},
{
"name": "pauseOnAsyncTask",
"name": "pauseOnAsyncCall",
"parameters": [
{ "name": "asyncTaskId", "$ref": "Runtime.AsyncTaskId", "description": "Debugger will pause when given async task is started." }
{ "name": "parentStackTraceId", "$ref": "Runtime.StackTraceId", "description": "Debugger will pause when async call with given stack trace is started." }
],
"experimental": true
},
......@@ -837,7 +832,7 @@
{ "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." }
{ "name": "asyncCallStackTraceId", "$ref": "Runtime.StackTraceId", "optional": true, "experimental": true, "description": "Just scheduled async call will have this stack trace as parent stack during async execution. This field is available only after <code>Debugger.stepInto</code> call with <code>breakOnAsynCall</code> flag." }
],
"description": "Fired when the virtual machine stopped on breakpoint or exception or any other stop criteria."
},
......
......@@ -1003,14 +1003,15 @@ void V8DebuggerAgentImpl::scheduleStepIntoAsync(
m_session->contextGroupId());
}
Response V8DebuggerAgentImpl::pauseOnAsyncTask(const String16& inAsyncTaskId) {
Response V8DebuggerAgentImpl::pauseOnAsyncCall(
std::unique_ptr<protocol::Runtime::StackTraceId> inParentStackTraceId) {
bool isOk = false;
int64_t task = inAsyncTaskId.toInteger64(&isOk);
int64_t stackTraceId = inParentStackTraceId->getId().toInteger64(&isOk);
if (!isOk) {
return Response::Error("Invalid asyncTaskId");
return Response::Error("Invalid stack trace id");
}
m_debugger->pauseOnAsyncTask(m_session->contextGroupId(),
reinterpret_cast<void*>(task));
m_debugger->pauseOnAsyncCall(m_session->contextGroupId(), stackTraceId,
inParentStackTraceId->getDebuggerId());
return Response::OK();
}
......@@ -1525,18 +1526,22 @@ void V8DebuggerAgentImpl::didPause(
Response response = currentCallFrames(&protocolCallFrames);
if (!response.isSuccess()) protocolCallFrames = Array<CallFrame>::create();
Maybe<String16> scheduledAsyncTaskId;
Maybe<protocol::Runtime::StackTraceId> asyncCallStackTrace;
void* rawScheduledAsyncTask = m_debugger->scheduledAsyncTask();
if (rawScheduledAsyncTask) {
String16Builder builder;
builder.appendNumber(reinterpret_cast<size_t>(rawScheduledAsyncTask));
scheduledAsyncTaskId = builder.toString();
asyncCallStackTrace =
protocol::Runtime::StackTraceId::create()
.setId(stackTraceIdToString(
reinterpret_cast<uintptr_t>(rawScheduledAsyncTask)))
.setDebuggerId(debuggerIdToString(
m_debugger->debuggerIdFor(m_session->contextGroupId())))
.build();
}
m_frontend.paused(std::move(protocolCallFrames), breakReason,
std::move(breakAuxData), std::move(hitBreakpointIds),
currentAsyncStackTrace(), currentExternalStackTrace(),
std::move(scheduledAsyncTaskId));
std::move(asyncCallStackTrace));
}
void V8DebuggerAgentImpl::didContinue() {
......
......@@ -93,7 +93,8 @@ class V8DebuggerAgentImpl : public protocol::Debugger::Backend {
Response stepOut() override;
void scheduleStepIntoAsync(
std::unique_ptr<ScheduleStepIntoAsyncCallback> callback) override;
Response pauseOnAsyncTask(const String16& inAsyncTaskId) override;
Response pauseOnAsyncCall(std::unique_ptr<protocol::Runtime::StackTraceId>
inParentStackTraceId) override;
Response setPauseOnExceptions(const String16& pauseState) override;
Response evaluateOnCallFrame(
const String16& callFrameId, const String16& expression,
......
......@@ -185,6 +185,7 @@ void V8Debugger::disable() {
clearContinueToLocation();
allAsyncTasksCanceled();
m_taskWithScheduledBreak = nullptr;
m_taskWithScheduledBreakDebuggerId = String16();
m_pauseOnAsyncCall = false;
m_wasmTranslation.Clear();
v8::debug::SetDebugDelegate(m_isolate, nullptr);
......@@ -324,10 +325,17 @@ void V8Debugger::scheduleStepIntoAsync(
m_stepIntoAsyncCallback = std::move(callback);
}
void V8Debugger::pauseOnAsyncTask(int targetContextGroupId, void* task) {
void V8Debugger::pauseOnAsyncCall(int targetContextGroupId, uintptr_t task,
const String16& debuggerId) {
DCHECK(targetContextGroupId);
m_targetContextGroupId = targetContextGroupId;
m_taskWithScheduledBreak = task;
m_taskWithScheduledBreak = reinterpret_cast<void*>(task);
String16 currentDebuggerId =
debuggerIdToString(debuggerIdFor(targetContextGroupId));
if (currentDebuggerId != debuggerId) {
m_taskWithScheduledBreakDebuggerId = debuggerId;
}
}
Response V8Debugger::continueToLocation(
......@@ -398,6 +406,7 @@ void V8Debugger::handleProgramBreak(
m_breakRequested = false;
m_pauseOnAsyncCall = false;
m_taskWithScheduledBreak = nullptr;
m_taskWithScheduledBreakDebuggerId = String16();
bool scheduledOOMBreak = m_scheduledOOMBreak;
bool scheduledAssertBreak = m_scheduledAssertBreak;
......@@ -758,6 +767,8 @@ V8StackTraceId V8Debugger::storeCurrentStackTrace(
++m_asyncStacksCount;
collectOldAsyncStacksIfNeeded();
asyncTaskCandidateForStepping(reinterpret_cast<void*>(id));
return V8StackTraceId(id, debuggerIdFor(contextGroupId));
}
......@@ -766,6 +777,14 @@ void V8Debugger::externalAsyncTaskStarted(const V8StackTraceId& parent) {
m_currentExternalParent.push_back(parent);
m_currentAsyncParent.emplace_back();
m_currentTasks.push_back(reinterpret_cast<void*>(parent.id));
if (m_breakRequested) return;
if (!m_taskWithScheduledBreakDebuggerId.isEmpty() &&
reinterpret_cast<uintptr_t>(m_taskWithScheduledBreak) == parent.id &&
m_taskWithScheduledBreakDebuggerId ==
debuggerIdToString(parent.debugger_id)) {
v8::debug::DebugBreak(m_isolate);
}
}
void V8Debugger::externalAsyncTaskFinished(const V8StackTraceId& parent) {
......@@ -774,6 +793,17 @@ void V8Debugger::externalAsyncTaskFinished(const V8StackTraceId& parent) {
m_currentAsyncParent.pop_back();
DCHECK(m_currentTasks.back() == reinterpret_cast<void*>(parent.id));
m_currentTasks.pop_back();
if (m_taskWithScheduledBreakDebuggerId.isEmpty() ||
reinterpret_cast<uintptr_t>(m_taskWithScheduledBreak) != parent.id ||
m_taskWithScheduledBreakDebuggerId !=
debuggerIdToString(parent.debugger_id)) {
return;
}
m_taskWithScheduledBreak = nullptr;
m_taskWithScheduledBreakDebuggerId = String16();
if (m_breakRequested) return;
v8::debug::CancelDebugBreak(m_isolate);
}
void V8Debugger::asyncTaskScheduled(const StringView& taskName, void* task,
......@@ -873,19 +903,26 @@ void V8Debugger::asyncTaskStartedForStepping(void* task) {
if (m_breakRequested) return;
// TODO(kozyatinskiy): we should search task in async chain to support
// blackboxing.
if (task != m_taskWithScheduledBreak) return;
v8::debug::DebugBreak(m_isolate);
if (m_taskWithScheduledBreakDebuggerId.isEmpty() &&
task == m_taskWithScheduledBreak) {
v8::debug::DebugBreak(m_isolate);
}
}
void V8Debugger::asyncTaskFinishedForStepping(void* task) {
if (task != m_taskWithScheduledBreak) return;
if (!m_taskWithScheduledBreakDebuggerId.isEmpty() ||
task != m_taskWithScheduledBreak) {
return;
}
m_taskWithScheduledBreak = nullptr;
if (m_breakRequested) return;
v8::debug::CancelDebugBreak(m_isolate);
}
void V8Debugger::asyncTaskCanceledForStepping(void* task) {
if (task != m_taskWithScheduledBreak) return;
if (!m_taskWithScheduledBreakDebuggerId.isEmpty() ||
task != m_taskWithScheduledBreak)
return;
m_taskWithScheduledBreak = nullptr;
}
......
......@@ -57,7 +57,8 @@ class V8Debugger : public v8::debug::DebugDelegate {
void scheduleStepIntoAsync(
std::unique_ptr<ScheduleStepIntoAsyncCallback> callback,
int targetContextGroupId);
void pauseOnAsyncTask(int targetContextGroupId, void* task);
void pauseOnAsyncCall(int targetContextGroupId, uintptr_t task,
const String16& debuggerId);
Response continueToLocation(int targetContextGroupId,
V8DebuggerScript* script,
......@@ -209,6 +210,7 @@ class V8Debugger : public v8::debug::DebugDelegate {
protocol::HashMap<V8DebuggerAgentImpl*, int> m_maxAsyncCallStackDepthMap;
void* m_taskWithScheduledBreak = nullptr;
String16 m_taskWithScheduledBreakDebuggerId;
std::unique_ptr<ScheduleStepIntoAsyncCallback> m_stepIntoAsyncCallback;
bool m_breakRequested = false;
......
......@@ -33,7 +33,7 @@ paused at:
Promise.resolve().#then(v => v * 2);
}
scheduledAsyncTaskId is set
asyncCallStackTraceId is set
paused at:
debugger;
......@@ -57,7 +57,7 @@ paused at:
p.#then(v => v * 2);
resolveCallback();
scheduledAsyncTaskId is set
asyncCallStackTraceId is set
paused at:
debugger;
......@@ -81,7 +81,7 @@ paused at:
Promise.resolve().#then(v => v * 2);
Promise.resolve().then(v => v * 4);
scheduledAsyncTaskId is set
asyncCallStackTraceId is set
paused at:
debugger;
......@@ -110,7 +110,7 @@ paused at:
Promise.resolve().#then(v => v * 4);
}
scheduledAsyncTaskId is set
asyncCallStackTraceId is set
paused at:
Promise.resolve().then(v => v * 2);
......@@ -134,7 +134,7 @@ paused at:
Promise.resolve().#then(v => v * 2);
debugger;
scheduledAsyncTaskId is set
asyncCallStackTraceId is set
paused at:
Promise.resolve().then(v => v * 2);
......@@ -151,7 +151,7 @@ paused at:
Promise.resolve().#then(v => v * 4);
}
scheduledAsyncTaskId is set
asyncCallStackTraceId is set
paused at:
debugger;
......@@ -175,7 +175,7 @@ paused at:
Promise.all([ Promise.resolve(), Promise.resolve() ]).#then(v => v * 2);
}
scheduledAsyncTaskId is set
asyncCallStackTraceId is set
paused at:
debugger;
......@@ -199,7 +199,7 @@ paused at:
createPromise().#then(v => v * 2);
}
scheduledAsyncTaskId is set
asyncCallStackTraceId is set
paused at:
debugger;
......
......@@ -75,8 +75,8 @@ InspectorTest.runAsyncTestSuite([
Protocol.Debugger.stepOver();
await waitPauseAndDumpLocation();
Protocol.Debugger.stepInto({breakOnAsyncCall: true});
let scheduledAsyncTaskId = await waitPauseAndDumpLocation();
Protocol.Debugger.pauseOnAsyncTask({asyncTaskId: scheduledAsyncTaskId});
let parentStackTraceId = await waitPauseAndDumpLocation();
Protocol.Debugger.pauseOnAsyncCall({parentStackTraceId});
Protocol.Debugger.resume();
await waitPauseAndDumpLocation();
await Protocol.Debugger.resume();
......@@ -88,8 +88,8 @@ InspectorTest.runAsyncTestSuite([
Protocol.Debugger.stepOver();
await waitPauseAndDumpLocation();
Protocol.Debugger.stepInto({breakOnAsyncCall: true});
let scheduledAsyncTaskId = await waitPauseAndDumpLocation();
Protocol.Debugger.pauseOnAsyncTask({asyncTaskId: scheduledAsyncTaskId});
let parentStackTraceId = await waitPauseAndDumpLocation();
Protocol.Debugger.pauseOnAsyncCall({parentStackTraceId});
Protocol.Debugger.resume();
await waitPauseAndDumpLocation();
await Protocol.Debugger.resume();
......@@ -101,8 +101,8 @@ InspectorTest.runAsyncTestSuite([
Protocol.Debugger.stepInto();
await waitPauseAndDumpLocation();
Protocol.Debugger.stepInto({breakOnAsyncCall: true});
let scheduledAsyncTaskId = await waitPauseAndDumpLocation();
Protocol.Debugger.pauseOnAsyncTask({asyncTaskId: scheduledAsyncTaskId});
let parentStackTraceId = await waitPauseAndDumpLocation();
Protocol.Debugger.pauseOnAsyncCall({parentStackTraceId});
Protocol.Debugger.resume();
await waitPauseAndDumpLocation();
await Protocol.Debugger.resume();
......@@ -116,8 +116,8 @@ InspectorTest.runAsyncTestSuite([
Protocol.Debugger.stepOver();
await waitPauseAndDumpLocation();
Protocol.Debugger.stepInto({breakOnAsyncCall: true});
let scheduledAsyncTaskId = await waitPauseAndDumpLocation();
Protocol.Debugger.pauseOnAsyncTask({asyncTaskId: scheduledAsyncTaskId});
let parentStackTraceId = await waitPauseAndDumpLocation();
Protocol.Debugger.pauseOnAsyncCall({parentStackTraceId});
Protocol.Debugger.resume();
await waitPauseAndDumpLocation();
await Protocol.Debugger.resume();
......@@ -129,15 +129,15 @@ InspectorTest.runAsyncTestSuite([
Protocol.Debugger.stepOver();
await waitPauseAndDumpLocation();
Protocol.Debugger.stepInto({breakOnAsyncCall: true});
let scheduledAsyncTaskId = await waitPauseAndDumpLocation();
Protocol.Debugger.pauseOnAsyncTask({asyncTaskId: scheduledAsyncTaskId});
let parentStackTraceId = await waitPauseAndDumpLocation();
Protocol.Debugger.pauseOnAsyncCall({parentStackTraceId});
Protocol.Debugger.resume();
await waitPauseAndDumpLocation();
Protocol.Debugger.stepOver();
await waitPauseAndDumpLocation();
Protocol.Debugger.stepInto({breakOnAsyncCall: true});
scheduledAsyncTaskId = await waitPauseAndDumpLocation();
Protocol.Debugger.pauseOnAsyncTask({asyncTaskId: scheduledAsyncTaskId});
parentStackTraceId = await waitPauseAndDumpLocation();
Protocol.Debugger.pauseOnAsyncCall({parentStackTraceId});
Protocol.Debugger.resume();
await waitPauseAndDumpLocation();
await Protocol.Debugger.resume();
......@@ -149,8 +149,8 @@ InspectorTest.runAsyncTestSuite([
Protocol.Debugger.stepOver();
await waitPauseAndDumpLocation();
Protocol.Debugger.stepInto({breakOnAsyncCall: true});
let scheduledAsyncTaskId = await waitPauseAndDumpLocation();
Protocol.Debugger.pauseOnAsyncTask({asyncTaskId: scheduledAsyncTaskId});
let parentStackTraceId = await waitPauseAndDumpLocation();
Protocol.Debugger.pauseOnAsyncCall({parentStackTraceId});
Protocol.Debugger.resume();
await waitPauseAndDumpLocation();
await Protocol.Debugger.resume();
......@@ -163,8 +163,8 @@ InspectorTest.runAsyncTestSuite([
await waitPauseAndDumpLocation();
await Protocol.Debugger.setBlackboxPatterns({patterns: ['framework\.js'] });
Protocol.Debugger.stepInto({breakOnAsyncCall: true});
let scheduledAsyncTaskId = await waitPauseAndDumpLocation();
Protocol.Debugger.pauseOnAsyncTask({asyncTaskId: scheduledAsyncTaskId});
let parentStackTraceId = await waitPauseAndDumpLocation();
Protocol.Debugger.pauseOnAsyncCall({parentStackTraceId});
Protocol.Debugger.resume();
await waitPauseAndDumpLocation();
await Protocol.Debugger.resume();
......@@ -172,11 +172,12 @@ InspectorTest.runAsyncTestSuite([
]);
async function waitPauseAndDumpLocation() {
var {params:{callFrames, scheduledAsyncTaskId}} = await Protocol.Debugger.oncePaused();
var {params: {callFrames, asyncCallStackTraceId}} =
await Protocol.Debugger.oncePaused();
InspectorTest.log('paused at:');
await session.logSourceLocation(callFrames[0].location);
if (scheduledAsyncTaskId) {
InspectorTest.log('scheduledAsyncTaskId is set\n');
if (asyncCallStackTraceId) {
InspectorTest.log('asyncCallStackTraceId is set\n');
}
return scheduledAsyncTaskId;
return asyncCallStackTraceId;
}
......@@ -2,12 +2,12 @@ Test for Debugger.stepInto with breakOnAsyncCall.
Running test: testSetTimeout
(anonymous) (test.js:0:0)
scheduledAsyncTaskId is set
asyncCallStackTraceId is set
setTimeout (test.js:0:11)
scheduledAsyncTaskId is empty
asyncCallStackTraceId is empty
Running test: testPromiseThen
(anonymous) (test.js:0:2)
scheduledAsyncTaskId is set
asyncCallStackTraceId is set
p.then (test.js:0:7)
scheduledAsyncTaskId is empty
asyncCallStackTraceId is empty
......@@ -15,18 +15,20 @@ InspectorTest.runAsyncTestSuite([
});
await pausedPromise;
Protocol.Debugger.stepInto({breakOnAsyncCall: true});
let {params:{callFrames, scheduledAsyncTaskId}} = await Protocol.Debugger.oncePaused();
let {params: {callFrames, asyncCallStackTraceId}} =
await Protocol.Debugger.oncePaused();
session.logCallFrames(callFrames);
if (scheduledAsyncTaskId) {
InspectorTest.log('scheduledAsyncTaskId is set');
if (asyncCallStackTraceId) {
InspectorTest.log('asyncCallStackTraceId is set');
}
Protocol.Debugger.pauseOnAsyncTask({asyncTaskId: scheduledAsyncTaskId});
Protocol.Debugger.pauseOnAsyncCall(
{parentStackTraceId: asyncCallStackTraceId});
pausedPromise = Protocol.Debugger.oncePaused();
Protocol.Debugger.resume();
({params:{callFrames, scheduledAsyncTaskId}} = await pausedPromise);
({params: {callFrames, asyncCallStackTraceId}} = await pausedPromise);
session.logCallFrames(callFrames);
if (!scheduledAsyncTaskId) {
InspectorTest.log('scheduledAsyncTaskId is empty');
if (!asyncCallStackTraceId) {
InspectorTest.log('asyncCallStackTraceId is empty');
}
await Protocol.Debugger.disable();
},
......@@ -39,18 +41,20 @@ InspectorTest.runAsyncTestSuite([
Protocol.Runtime.evaluate({expression: 'p.then(() => 42)//# sourceURL=test.js'});
await pausedPromise;
Protocol.Debugger.stepInto({breakOnAsyncCall: true});
let {params:{callFrames, scheduledAsyncTaskId}} = await Protocol.Debugger.oncePaused();
let {params: {callFrames, asyncCallStackTraceId}} =
await Protocol.Debugger.oncePaused();
session.logCallFrames(callFrames);
if (scheduledAsyncTaskId) {
InspectorTest.log('scheduledAsyncTaskId is set');
if (asyncCallStackTraceId) {
InspectorTest.log('asyncCallStackTraceId is set');
}
Protocol.Debugger.pauseOnAsyncTask({asyncTaskId: scheduledAsyncTaskId});
Protocol.Debugger.pauseOnAsyncCall(
{parentStackTraceId: asyncCallStackTraceId});
pausedPromise = Protocol.Debugger.oncePaused();
Protocol.Debugger.resume();
({params:{callFrames, scheduledAsyncTaskId}} = await pausedPromise);
({params: {callFrames, asyncCallStackTraceId}} = await pausedPromise);
session.logCallFrames(callFrames);
if (!scheduledAsyncTaskId) {
InspectorTest.log('scheduledAsyncTaskId is empty');
if (!asyncCallStackTraceId) {
InspectorTest.log('asyncCallStackTraceId is empty');
}
await Protocol.Debugger.disable();
}
......
Test for step-into remote async task
Setup debugger agents..
Pause before stack trace is captured..
Run stepInto with breakOnAsyncCall flag
Call pauseOnAsyncCall
Trigger external async task on another context group
Dump stack trace
boo (target.js:1:18)
call (framework.js:3:2)
(anonymous) (target.js:0:0)
-- remote-task --
store (utils.js:2:25)
foo (source.js:1:13)
(anonymous) (source.js:2:6)
// 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('Test for step-into remote async task');
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(',') + ']';
}
//# sourceURL=utils.js`;
contextGroup1.addScript(utilsScript);
contextGroup2.addScript(utilsScript);
let frameworkScript = `
function call(id, f) {
inspector.externalAsyncTaskStarted(Int32Array.from(JSON.parse(id)).buffer);
f();
inspector.externalAsyncTaskFinished(Int32Array.from(JSON.parse(id)).buffer);
}
//# sourceURL=framework.js`;
contextGroup1.addScript(frameworkScript);
contextGroup2.addScript(frameworkScript);
session1.setupScriptMap();
session2.setupScriptMap();
(async function test() {
InspectorTest.log('Setup debugger agents..');
let debuggerId1 = (await Protocol1.Debugger.enable()).result.debuggerId;
let debuggerId2 = (await Protocol2.Debugger.enable()).result.debuggerId;
Protocol1.Debugger.setAsyncCallStackDepth({maxDepth: 128});
Protocol2.Debugger.setAsyncCallStackDepth({maxDepth: 128});
Protocol1.Debugger.setBlackboxPatterns({patterns: ['framework\.js']});
Protocol2.Debugger.setBlackboxPatterns({patterns: ['framework\.js']});
InspectorTest.log('Pause before stack trace is captured..');
Protocol1.Debugger.setBreakpointByUrl(
{lineNumber: 2, columnNumber: 25, url: 'utils.js'});
let evaluatePromise = Protocol1.Runtime.evaluate({
expression: `(function foo() {
return store('remote-task');
})()
//# sourceURL=source.js`
});
await Protocol1.Debugger.oncePaused();
InspectorTest.log('Run stepInto with breakOnAsyncCall flag');
Protocol1.Debugger.stepInto({breakOnAsyncCall: true});
let {params: {asyncCallStackTraceId}} = await Protocol1.Debugger.oncePaused();
InspectorTest.log('Call pauseOnAsyncCall');
Protocol2.Debugger.pauseOnAsyncCall({
parentStackTraceId: asyncCallStackTraceId,
});
Protocol1.Debugger.resume();
InspectorTest.log('Trigger external async task on another context group');
let stackTraceId = (await evaluatePromise).result.result.value;
Protocol2.Runtime.evaluate({
expression: `call('${stackTraceId}',
function boo() {})
//# sourceURL=target.js`
});
InspectorTest.log('Dump stack trace');
let {params: {callFrames, asyncStackTraceId}} =
await Protocol2.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.setAsyncCallStackDepth({maxDepth: 0});
Protocol2.Debugger.setAsyncCallStackDepth({maxDepth: 0});
await Protocol1.Debugger.disable();
await Protocol2.Debugger.disable();
InspectorTest.completeTest();
})()
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