Make debugger step into bound callbacks passed to Array.forEach.

BUG=chromium:450004
R=yangguo@chromium.org, kozyatinskiy@chromium.org
LOG=N

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

Cr-Commit-Position: refs/heads/master@{#27419}
This commit is contained in:
aandrey 2015-03-24 09:02:03 -07:00 committed by Commit bot
parent 82004a5e46
commit fc1689392e
3 changed files with 78 additions and 8 deletions

View File

@ -2738,7 +2738,7 @@ RUNTIME_FUNCTION(Runtime_GetScript) {
}
// Check whether debugger and is about to step into the callback that is passed
// Check whether debugger is about to step into the callback that is passed
// to a built-in function such as Array.forEach.
RUNTIME_FUNCTION(Runtime_DebugCallbackSupportsStepping) {
DCHECK(args.length() == 1);
@ -2748,9 +2748,12 @@ RUNTIME_FUNCTION(Runtime_DebugCallbackSupportsStepping) {
return isolate->heap()->false_value();
}
CONVERT_ARG_CHECKED(Object, callback, 0);
// We do not step into the callback if it's a builtin or not even a function.
return isolate->heap()->ToBoolean(callback->IsJSFunction() &&
!JSFunction::cast(callback)->IsBuiltin());
// We do not step into the callback if it's a builtin other than a bound,
// or not even a function.
return isolate->heap()->ToBoolean(
callback->IsJSFunction() &&
(!JSFunction::cast(callback)->IsBuiltin() ||
JSFunction::cast(callback)->shared()->bound()));
}
@ -2775,7 +2778,7 @@ RUNTIME_FUNCTION(Runtime_DebugPrepareStepInIfStepping) {
// if we do not leave the builtin. To be able to step into the function
// again, we need to clear the step out at this point.
debug->ClearStepOut();
debug->FloodWithOneShot(fun);
debug->FloodWithOneShotGeneric(fun);
return isolate->heap()->undefined_value();
}

View File

@ -37,15 +37,17 @@ function listener(event, exec_state, event_data, data) {
};
Debug.setListener(listener);
var bound_callback = callback.bind(null);
debugger; // Break 0.
[1,2].forEach(callback); // Break 1.
[3,4].forEach(bound_callback); // Break 6.
function callback(x) {
return x; // Break 2. // Break 4.
} // Break 3. // Break 5.
return x; // Break 2. // Break 4. // Break 7. // Break 9.
} // Break 3. // Break 5. // Break 8. // Break 10.
assertNull(exception); // Break 6.
assertNull(exception); // Break 11.
assertEquals(expected_breaks, break_count);
Debug.setListener(null);

View File

@ -0,0 +1,65 @@
// Copyright 2015 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.
// Flags: --expose-debug-as debug --allow-natives-syntax --noalways-opt
// Tests stepping into through Promises.
Debug = debug.Debug
var exception = null;
var break_count = 0;
var expected_breaks = -1;
function listener(event, exec_state, event_data, data) {
try {
if (event == Debug.DebugEvent.Break) {
assertTrue(exec_state.frameCount() != 0, "FAIL: Empty stack trace");
if (!break_count) {
// Count number of expected breakpoints in this source file.
var source_text = exec_state.frame(0).func().script().source();
expected_breaks = source_text.match(/\/\/\s*Break\s+\d+\./g).length;
print("Expected breaks: " + expected_breaks);
}
var source = exec_state.frame(0).sourceLineText();
print("paused at: " + source);
assertTrue(source.indexOf("// Break " + break_count + ".") > 0,
"Unexpected pause at: " + source + "\n" +
"Expected: // Break " + break_count + ".");
++break_count;
if (break_count !== expected_breaks) {
exec_state.prepareStep(Debug.StepAction.StepIn, 1);
}
}
} catch(e) {
exception = e;
print(e, e.stack);
}
};
Debug.setListener(listener);
Promise.resolve(42)
.then(
function f0() {
debugger; // Break 0.
} // Break 1.
)
.then(callback)
.then(callback.bind(null))
.then(Object)
.then(callback.bind(null).bind(null))
.then(finalize)
.catch(function(err) {
%AbortJS("FAIL: " + err);
});
function callback(x) {
return x; // Break 2. // Break 4. // Break 6.
} // Break 3. // Break 5. // Break 7.
function finalize() {
assertNull(exception); // Break 8.
assertEquals(expected_breaks, break_count);
Debug.setListener(null);
}