| 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();
|
| }
|
|
|
|
|