Commit 42a10a9d authored by peter.rybin@gmail.com's avatar peter.rybin@gmail.com

Allow debugger evaluate expressions to mute local variables

R=yangguo@chromium.org

Review URL: https://codereview.chromium.org/17636007

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@15323 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent cecbe44e
...@@ -1699,13 +1699,30 @@ FrameMirror.prototype.stepInPositions = function() { ...@@ -1699,13 +1699,30 @@ FrameMirror.prototype.stepInPositions = function() {
FrameMirror.prototype.evaluate = function(source, disable_break, FrameMirror.prototype.evaluate = function(source, disable_break,
opt_context_object) { opt_context_object) {
var result = %DebugEvaluate(this.break_id_, var result_array = %DebugEvaluate(this.break_id_,
this.details_.frameId(), this.details_.frameId(),
this.details_.inlinedFrameIndex(), this.details_.inlinedFrameIndex(),
source, source,
Boolean(disable_break), Boolean(disable_break),
opt_context_object); opt_context_object);
return MakeMirror(result); // Silently ignore local variables changes if the frame is optimized.
if (!this.isOptimizedFrame()) {
var local_scope_before = result_array[1];
var local_scope_after = result_array[2];
for (var n in local_scope_after) {
var value_before = local_scope_before[n];
var value_after = local_scope_after[n];
if (value_before !== value_after) {
%SetScopeVariableValue(this.break_id_,
this.details_.frameId(),
this.details_.inlinedFrameIndex(),
0,
n,
value_after);
}
}
}
return MakeMirror(result_array[0]);
}; };
......
...@@ -12424,6 +12424,13 @@ static MaybeObject* DebugEvaluate(Isolate* isolate, ...@@ -12424,6 +12424,13 @@ static MaybeObject* DebugEvaluate(Isolate* isolate,
// the same view of the values of parameters and local variables as if the // the same view of the values of parameters and local variables as if the
// piece of JavaScript was evaluated at the point where the function on the // piece of JavaScript was evaluated at the point where the function on the
// stack frame is currently stopped when we compile and run the (direct) eval. // stack frame is currently stopped when we compile and run the (direct) eval.
// Returns array of
// #0: evaluate result
// #1: local variables scope materizalized as object before evaluation
// #2: local variables scope materizalized as object after evaluation
// Since user expression only reaches (and modifies) copies of local variables,
// those copies are returned to the caller to allow tracking the changes and
// manually updating the actual variables.
RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) { RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) {
HandleScope scope(isolate); HandleScope scope(isolate);
...@@ -12523,7 +12530,23 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) { ...@@ -12523,7 +12530,23 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugEvaluate) {
} }
Handle<Object> receiver(frame->receiver(), isolate); Handle<Object> receiver(frame->receiver(), isolate);
return DebugEvaluate(isolate, context, context_extension, receiver, source); Object* evaluate_result_object;
{ MaybeObject* maybe_result =
DebugEvaluate(isolate, context, context_extension, receiver, source);
if (!maybe_result->ToObject(&evaluate_result_object)) return maybe_result;
}
Handle<Object> evaluate_result(evaluate_result_object, isolate);
Handle<JSObject> local_scope_after = MaterializeLocalScopeWithFrameInspector(
isolate, frame, &frame_inspector);
Handle<FixedArray> resultArray =
isolate->factory()->NewFixedArray(3);
resultArray->set(0, *evaluate_result);
resultArray->set(2, *local_scope);
resultArray->set(1, *local_scope_after);
return *(isolate->factory()->NewJSArrayWithElements(resultArray));
} }
......
...@@ -38,6 +38,7 @@ function h() { ...@@ -38,6 +38,7 @@ function h() {
var b = 2; var b = 2;
var eval = 5; // Overriding eval should not break anything. var eval = 5; // Overriding eval should not break anything.
debugger; // Breakpoint. debugger; // Breakpoint.
return a;
} }
function checkFrame0(frame) { function checkFrame0(frame) {
...@@ -60,7 +61,7 @@ function checkFrame0(frame) { ...@@ -60,7 +61,7 @@ function checkFrame0(frame) {
function g() { function g() {
var a = 3; var a = 3;
eval("var b = 4;"); eval("var b = 4;");
h(); return h() + a;
} }
function checkFrame1(frame) { function checkFrame1(frame) {
...@@ -83,7 +84,7 @@ function f() { ...@@ -83,7 +84,7 @@ function f() {
var a = 5; var a = 5;
var b = 0; var b = 0;
with ({b:6}) { with ({b:6}) {
g(); return g();
} }
} }
...@@ -125,6 +126,10 @@ function listener(event, exec_state, event_data, data) { ...@@ -125,6 +126,10 @@ function listener(event, exec_state, event_data, data) {
assertEquals(6, exec_state.frame(2).evaluate('b').value()); assertEquals(6, exec_state.frame(2).evaluate('b').value());
assertEquals("function", assertEquals("function",
typeof exec_state.frame(2).evaluate('eval').value()); typeof exec_state.frame(2).evaluate('eval').value());
assertEquals("foo",
exec_state.frame(0).evaluate('a = "foo"').value());
assertEquals("bar",
exec_state.frame(1).evaluate('a = "bar"').value());
// Indicate that all was processed. // Indicate that all was processed.
listenerComplete = true; listenerComplete = true;
} }
...@@ -137,7 +142,9 @@ function listener(event, exec_state, event_data, data) { ...@@ -137,7 +142,9 @@ function listener(event, exec_state, event_data, data) {
// Add the debug event listener. // Add the debug event listener.
Debug.setListener(listener); Debug.setListener(listener);
f(); var f_result = f();
assertEquals('foobar', f_result);
// Make sure that the debug event listener was invoked. // Make sure that the debug event listener was invoked.
assertFalse(exception, "exception in listener") assertFalse(exception, "exception in listener")
......
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