[inspector] Pass the Context into terminateExecution

Adding and removing the MicrotasksCompletedCallback should be
associated with the microtask queue of the Context. We store the
context as WeakPtr and always remove the callback when it completes
regardless of the state of the debugger.

BUG=v8:13450

Change-Id: I40d623b05952575febfb76accc15512a38d14ab9
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4004602
Commit-Queue: Dave Tapuska <dtapuska@chromium.org>
Reviewed-by: Simon Zünd <szuend@chromium.org>
Reviewed-by: Camillo Bruni <cbruni@chromium.org>
Cr-Commit-Position: refs/heads/main@{#84302}
This commit is contained in:
Dave Tapuska 2022-11-08 17:36:23 -05:00 committed by V8 LUCI CQ
parent 0861b4b658
commit 8016f5c667
3 changed files with 43 additions and 10 deletions

View File

@ -84,8 +84,14 @@ V8Debugger::V8Debugger(v8::Isolate* isolate, V8InspectorImpl* inspector)
V8Debugger::~V8Debugger() {
m_isolate->RemoveCallCompletedCallback(
&V8Debugger::terminateExecutionCompletedCallback);
m_isolate->RemoveMicrotasksCompletedCallback(
&V8Debugger::terminateExecutionCompletedCallbackIgnoringData);
if (!m_terminateExecutionCallbackContext.IsEmpty()) {
v8::MicrotaskQueue* microtask_queue =
m_terminateExecutionCallbackContext.Get(m_isolate)
->GetMicrotaskQueue();
microtask_queue->RemoveMicrotasksCompletedCallback(
&V8Debugger::terminateExecutionCompletedCallbackIgnoringData,
microtask_queue);
}
}
void V8Debugger::enable() {
@ -283,6 +289,7 @@ void V8Debugger::stepOutOfFunction(int targetContextGroupId) {
}
void V8Debugger::terminateExecution(
v8::Local<v8::Context> context,
std::unique_ptr<TerminateExecutionCallback> callback) {
if (m_terminateExecutionCallback) {
if (callback) {
@ -292,22 +299,35 @@ void V8Debugger::terminateExecution(
return;
}
m_terminateExecutionCallback = std::move(callback);
m_terminateExecutionCallbackContext.Reset(m_isolate, context);
m_terminateExecutionCallbackContext.SetWeak();
m_isolate->AddCallCompletedCallback(
&V8Debugger::terminateExecutionCompletedCallback);
m_isolate->AddMicrotasksCompletedCallback(
&V8Debugger::terminateExecutionCompletedCallbackIgnoringData);
v8::MicrotaskQueue* microtask_queue = context->GetMicrotaskQueue();
microtask_queue->AddMicrotasksCompletedCallback(
&V8Debugger::terminateExecutionCompletedCallbackIgnoringData,
microtask_queue);
m_isolate->TerminateExecution();
}
void V8Debugger::reportTermination() {
if (!m_terminateExecutionCallback) return;
if (!m_terminateExecutionCallback) {
DCHECK(m_terminateExecutionCallbackContext.IsEmpty());
return;
}
m_isolate->RemoveCallCompletedCallback(
&V8Debugger::terminateExecutionCompletedCallback);
m_isolate->RemoveMicrotasksCompletedCallback(
&V8Debugger::terminateExecutionCompletedCallbackIgnoringData);
if (!m_terminateExecutionCallbackContext.IsEmpty()) {
v8::MicrotaskQueue* microtask_queue =
m_terminateExecutionCallbackContext.Get(m_isolate)->GetMicrotaskQueue();
microtask_queue->RemoveMicrotasksCompletedCallback(
&V8Debugger::terminateExecutionCompletedCallbackIgnoringData,
microtask_queue);
}
m_isolate->CancelTerminateExecution();
m_terminateExecutionCallback->sendSuccess();
m_terminateExecutionCallback.reset();
m_terminateExecutionCallbackContext.Reset();
}
void V8Debugger::terminateExecutionCompletedCallback(v8::Isolate* isolate) {
@ -318,7 +338,12 @@ void V8Debugger::terminateExecutionCompletedCallback(v8::Isolate* isolate) {
}
void V8Debugger::terminateExecutionCompletedCallbackIgnoringData(
v8::Isolate* isolate, void*) {
v8::Isolate* isolate, void* data) {
DCHECK(data);
// Ensure that after every microtask completed callback we remove the
// callback regardless of how `terminateExecutionCompletedCallback` behaves.
static_cast<v8::MicrotaskQueue*>(data)->RemoveMicrotasksCompletedCallback(
&V8Debugger::terminateExecutionCompletedCallbackIgnoringData, data);
terminateExecutionCompletedCallback(isolate);
}

View File

@ -71,7 +71,8 @@ class V8Debugger : public v8::debug::DebugDelegate,
void stepOverStatement(int targetContextGroupId);
void stepOutOfFunction(int targetContextGroupId);
void terminateExecution(std::unique_ptr<TerminateExecutionCallback> callback);
void terminateExecution(v8::Local<v8::Context> context,
std::unique_ptr<TerminateExecutionCallback> callback);
Response continueToLocation(int targetContextGroupId,
V8DebuggerScript* script,
@ -297,6 +298,7 @@ class V8Debugger : public v8::debug::DebugDelegate,
std::unordered_map<int, internal::V8DebuggerId> m_contextGroupIdToDebuggerId;
std::unique_ptr<TerminateExecutionCallback> m_terminateExecutionCallback;
v8::Global<v8::Context> m_terminateExecutionCallbackContext;
};
} // namespace v8_inspector

View File

@ -709,7 +709,13 @@ Response V8RuntimeAgentImpl::getHeapUsage(double* out_usedSize,
void V8RuntimeAgentImpl::terminateExecution(
std::unique_ptr<TerminateExecutionCallback> callback) {
m_inspector->debugger()->terminateExecution(std::move(callback));
v8::HandleScope handles(m_inspector->isolate());
v8::Local<v8::Context> defaultContext =
m_inspector->client()->ensureDefaultContextInGroup(
m_session->contextGroupId());
m_inspector->debugger()->terminateExecution(defaultContext,
std::move(callback));
}
namespace {