From 0a384a708dff08158987d601e3e24fc5393fe9cd Mon Sep 17 00:00:00 2001 From: "yurys@chromium.org" Date: Mon, 16 Nov 2009 14:41:55 +0000 Subject: [PATCH] Skip debugger frames when looking for calling context. BUG=509 Review URL: http://codereview.chromium.org/398002 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3310 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/top.cc | 13 ++++++ test/cctest/test-debug.cc | 83 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+) diff --git a/src/top.cc b/src/top.cc index ca2a951d18..75aa5cdb2d 100644 --- a/src/top.cc +++ b/src/top.cc @@ -929,6 +929,19 @@ Handle Top::global_context() { Handle Top::GetCallingGlobalContext() { JavaScriptFrameIterator it; +#ifdef ENABLE_DEBUGGER_SUPPORT + if (Debug::InDebugger()) { + while (!it.done()) { + JavaScriptFrame* frame = it.frame(); + Context* context = Context::cast(frame->context()); + if (context->global_context() == *Debug::debug_context()) { + it.Advance(); + } else { + break; + } + } + } +#endif // ENABLE_DEBUGGER_SUPPORT if (it.done()) return Handle::null(); JavaScriptFrame* frame = it.frame(); Context* context = Context::cast(frame->context()); diff --git a/test/cctest/test-debug.cc b/test/cctest/test-debug.cc index 84f547a5c3..12e5617112 100644 --- a/test/cctest/test-debug.cc +++ b/test/cctest/test-debug.cc @@ -5605,3 +5605,86 @@ TEST(DebugBreakFunctionApply) { v8::Debug::SetDebugEventListener(NULL); CheckDebuggerUnloaded(); } + + +v8::Handle debugee_context; +v8::Handle debugger_context; + + +// Property getter that checks that current and calling contexts +// are both the debugee contexts. +static v8::Handle NamedGetterWithCallingContextCheck( + v8::Local name, + const v8::AccessorInfo& info) { + CHECK(strcmp(*v8::String::AsciiValue(name), "a") == 0); + v8::Handle current = v8::Context::GetCurrent(); + CHECK(current == debugee_context); + CHECK(current != debugger_context); + v8::Handle calling = v8::Context::GetCalling(); + CHECK(calling == debugee_context); + CHECK(calling != debugger_context); + return v8::Int32::New(1); +} + + +// Debug event listener that checks if the first argument of a function is +// an object with property 'a' == 1. If the property has custom accessor +// this handler will eventually invoke it. +static void DebugEventGetAtgumentPropertyValue( + v8::DebugEvent event, + v8::Handle exec_state, + v8::Handle event_data, + v8::Handle data) { + if (event == v8::Break) { + break_point_hit_count++; + CHECK(debugger_context == v8::Context::GetCurrent()); + v8::Handle func(v8::Function::Cast(*CompileRun( + "(function(exec_state) {\n" + " return (exec_state.frame(0).argumentValue(0).property('a').\n" + " value().value() == 1);\n" + "})"))); + const int argc = 1; + v8::Handle argv[argc] = { exec_state }; + v8::Handle result = func->Call(exec_state, argc, argv); + CHECK(result->IsTrue()); + } +} + + +TEST(CallingContextIsNotDebugContext) { + // Create and enter a debugee context. + v8::HandleScope scope; + DebugLocalContext env; + env.ExposeDebug(); + + // Save handles to the debugger and debugee contexts to be used in + // NamedGetterWithCallingContextCheck. + debugee_context = v8::Local(*env); + debugger_context = v8::Utils::ToLocal(Debug::debug_context()); + + // Create object with 'a' property accessor. + v8::Handle named = v8::ObjectTemplate::New(); + named->SetAccessor(v8::String::New("a"), + NamedGetterWithCallingContextCheck); + env->Global()->Set(v8::String::New("obj"), + named->NewInstance()); + + // Register the debug event listener + v8::Debug::SetDebugEventListener(DebugEventGetAtgumentPropertyValue); + + // Create a function that invokes debugger. + v8::Local foo = CompileFunction( + &env, + "function bar(x) { debugger; }" + "function foo(){ bar(obj); }", + "foo"); + + break_point_hit_count = 0; + foo->Call(env->Global(), 0, NULL); + CHECK_EQ(1, break_point_hit_count); + + v8::Debug::SetDebugEventListener(NULL); + debugee_context = v8::Handle(); + debugger_context = v8::Handle(); + CheckDebuggerUnloaded(); +}