Index: src/runtime/runtime-debug.cc |
diff --git a/src/runtime/runtime-debug.cc b/src/runtime/runtime-debug.cc |
index 07737d09d7ed330b0b8f3e43ad5f94acd0b89ea5..35379a40884bfc4e51cb6caabf992904768fb4b9 100644 |
--- a/src/runtime/runtime-debug.cc |
+++ b/src/runtime/runtime-debug.cc |
@@ -1612,33 +1612,55 @@ RUNTIME_FUNCTION(Runtime_GetScript) { |
} |
+bool DebugStepInIsActive(Debug* debug) { |
+ return debug->is_active() && debug->IsStepping() && |
+ debug->last_step_action() == StepIn; |
+} |
+ |
+ |
// Check whether debugger is about to step into the callback that is passed |
-// to a built-in function such as Array.forEach. |
+// to a built-in function such as Array.forEach. This check is done before |
+// %DebugPrepareStepInIfStepping and is not strictly necessary. However, if it |
+// returns false, we can skip %DebugPrepareStepInIfStepping, useful in loops. |
RUNTIME_FUNCTION(Runtime_DebugCallbackSupportsStepping) { |
+ SealHandleScope shs(isolate); |
DCHECK(args.length() == 1); |
- Debug* debug = isolate->debug(); |
- if (!debug->is_active() || !debug->IsStepping() || |
- debug->last_step_action() != StepIn) { |
+ if (!DebugStepInIsActive(isolate->debug())) { |
return isolate->heap()->false_value(); |
} |
- CONVERT_ARG_CHECKED(Object, callback, 0); |
+ CONVERT_ARG_CHECKED(Object, object, 0); |
+ RUNTIME_ASSERT(object->IsJSFunction() || object->IsJSGeneratorObject()); |
// 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)->IsSubjectToDebugging() || |
- JSFunction::cast(callback)->shared()->bound())); |
+ JSFunction* fun; |
+ if (object->IsJSFunction()) { |
+ fun = JSFunction::cast(object); |
+ } else { |
+ fun = JSGeneratorObject::cast(object)->function(); |
+ } |
+ return isolate->heap()->ToBoolean(fun->IsSubjectToDebugging() || |
+ fun->shared()->bound()); |
+} |
+ |
+ |
+void FloodDebugSubjectWithOneShot(Debug* debug, Handle<JSFunction> function) { |
+ if (function->IsSubjectToDebugging() || function->shared()->bound()) { |
+ // When leaving the function, step out has been activated, but not performed |
+ // 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->FloodWithOneShotGeneric(function); |
+ } |
} |
// Set one shot breakpoints for the callback function that is passed to a |
-// built-in function such as Array.forEach to enable stepping into the callback. |
+// built-in function such as Array.forEach to enable stepping into the callback, |
+// if we are indeed stepping and the callback is subject to debugging. |
RUNTIME_FUNCTION(Runtime_DebugPrepareStepInIfStepping) { |
DCHECK(args.length() == 1); |
- RUNTIME_ASSERT(isolate->debug()->is_active()); |
- |
Debug* debug = isolate->debug(); |
- if (!debug->IsStepping()) return isolate->heap()->undefined_value(); |
+ if (!DebugStepInIsActive(debug)) return isolate->heap()->undefined_value(); |
HandleScope scope(isolate); |
CONVERT_ARG_HANDLE_CHECKED(Object, object, 0); |
@@ -1650,21 +1672,23 @@ RUNTIME_FUNCTION(Runtime_DebugPrepareStepInIfStepping) { |
fun = Handle<JSFunction>( |
Handle<JSGeneratorObject>::cast(object)->function(), isolate); |
} |
- // When leaving the function, step out has been activated, but not performed |
- // 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->FloodWithOneShotGeneric(fun); |
+ |
+ FloodDebugSubjectWithOneShot(debug, fun); |
return isolate->heap()->undefined_value(); |
} |
RUNTIME_FUNCTION(Runtime_DebugPushPromise) { |
- DCHECK(args.length() == 2); |
+ DCHECK(args.length() == 3); |
HandleScope scope(isolate); |
CONVERT_ARG_HANDLE_CHECKED(JSObject, promise, 0); |
CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 1); |
+ CONVERT_ARG_HANDLE_CHECKED(Object, handler, 2); |
isolate->PushPromise(promise, function); |
+ Debug* debug = isolate->debug(); |
+ if (handler->IsJSFunction() && DebugStepInIsActive(debug)) { |
+ FloodDebugSubjectWithOneShot(debug, Handle<JSFunction>::cast(handler)); |
+ } |
return isolate->heap()->undefined_value(); |
} |