Add a convenience method to get the debugged context

Since the generic GetCallingContext is deprecated, but there's still the
use case for the debugger to get the currently debugged context while in
the debug context, add a convenience API for it.

Note that EventDetails already exposes this context, but the embedder
might not necessarily have the EventDetails around.

R=verwaest@chromium.org
BUG=

Review-Url: https://codereview.chromium.org/2040853003
Cr-Commit-Position: refs/heads/master@{#36751}
This commit is contained in:
jochen 2016-06-06 07:11:29 -07:00 committed by Commit bot
parent 4fb3051da2
commit 37394eb3b0
5 changed files with 54 additions and 0 deletions

View File

@ -125,6 +125,8 @@ class V8_EXPORT Debug {
*/
virtual ClientData* GetClientData() const = 0;
virtual Isolate* GetIsolate() const = 0;
virtual ~EventDetails() {}
};
@ -259,6 +261,11 @@ class V8_EXPORT Debug {
V8_DEPRECATED("Use version with an Isolate",
static Local<Context> GetDebugContext());
/**
* While in the debug context, this method returns the top-most non-debug
* context, if it exists.
*/
static MaybeLocal<Context> GetDebuggedContext(Isolate* isolate);
/**
* Enable/disable LiveEdit functionality for the given Isolate

View File

@ -8123,6 +8123,14 @@ Local<Context> Debug::GetDebugContext() {
return GetDebugContext(reinterpret_cast<Isolate*>(i::Isolate::Current()));
}
MaybeLocal<Context> Debug::GetDebuggedContext(Isolate* isolate) {
i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
ENTER_V8(i_isolate);
if (!i_isolate->debug()->in_debug_scope()) return MaybeLocal<Context>();
i::Handle<i::Object> calling = i_isolate->GetCallingNativeContext();
if (calling.is_null()) return MaybeLocal<Context>();
return Utils::ToLocal(i::Handle<i::Context>::cast(calling));
}
void Debug::SetLiveEditEnabled(Isolate* isolate, bool enable) {
i::Isolate* internal_isolate = reinterpret_cast<i::Isolate*>(isolate);

View File

@ -2512,6 +2512,9 @@ v8::Debug::ClientData* EventDetailsImpl::GetClientData() const {
return client_data_;
}
v8::Isolate* EventDetailsImpl::GetIsolate() const {
return reinterpret_cast<v8::Isolate*>(exec_state_->GetIsolate());
}
CommandMessage::CommandMessage() : text_(Vector<uint16_t>::empty()),
client_data_(NULL) {

View File

@ -305,6 +305,8 @@ class EventDetailsImpl : public v8::Debug::EventDetails {
virtual v8::Local<v8::Context> GetEventContext() const;
virtual v8::Local<v8::Value> GetCallbackData() const;
virtual v8::Debug::ClientData* GetClientData() const;
virtual v8::Isolate* GetIsolate() const;
private:
DebugEvent event_; // Debug event causing the break.
Handle<JSObject> exec_state_; // Current execution state.

View File

@ -7180,6 +7180,40 @@ TEST(NoDebugContextWhenDebuggerDisabled) {
CHECK(context.IsEmpty());
}
static void DebugEventCheckContext(
const v8::Debug::EventDetails& event_details) {
if (event_details.GetEvent() == v8::Break) {
v8::Isolate* isolate = event_details.GetIsolate();
CHECK(v8::Debug::GetDebuggedContext(isolate)
.ToLocalChecked()
->Global()
->Equals(isolate->GetCurrentContext(),
event_details.GetEventContext()->Global())
.FromJust());
}
}
static void CheckContext(const v8::FunctionCallbackInfo<v8::Value>& args) {
CHECK(v8::Debug::GetDebuggedContext(args.GetIsolate()).IsEmpty());
}
TEST(DebuggedContext) {
DebugLocalContext env;
v8::Isolate* isolate = env->GetIsolate();
v8::Debug::SetDebugEventListener(isolate, DebugEventCheckContext);
v8::Local<v8::Function> foo =
CompileFunction(&env, "function foo(){bar=0;}", "foo");
SetBreakPoint(foo, 0);
foo->Call(env.context(), env->Global(), 0, nullptr).ToLocalChecked();
v8::Local<v8::Function> fun = v8::FunctionTemplate::New(isolate, CheckContext)
->GetFunction(env.context())
.ToLocalChecked();
fun->Call(env.context(), env->Global(), 0, nullptr).ToLocalChecked();
}
static v8::Local<v8::Value> expected_callback_data;
static void DebugEventContextChecker(const v8::Debug::EventDetails& details) {