| Index: src/runtime/runtime-debug.cc
|
| diff --git a/src/runtime/runtime-debug.cc b/src/runtime/runtime-debug.cc
|
| index 1ffaa5f95cab4d1e06d8f0b7b70b47c73c0068ec..8bdec1061b1f92af06c7938db61fdbe7d9b7c83c 100644
|
| --- a/src/runtime/runtime-debug.cc
|
| +++ b/src/runtime/runtime-debug.cc
|
| @@ -1633,15 +1633,50 @@
|
| }
|
|
|
|
|
| +// Check whether debugger is about to step into the callback that is passed
|
| +// 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);
|
| + if (!DebugStepInIsActive(isolate->debug())) {
|
| + return isolate->heap()->false_value();
|
| + }
|
| + 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.
|
| + JSFunction* fun;
|
| + if (object->IsJSFunction()) {
|
| + fun = JSFunction::cast(object);
|
| + } else {
|
| + fun = JSGeneratorObject::cast(object)->function();
|
| + }
|
| + return isolate->heap()->ToBoolean(fun->shared()->IsSubjectToDebugging() ||
|
| + fun->shared()->bound());
|
| +}
|
| +
|
| +
|
| +void FloodDebugSubjectWithOneShot(Debug* debug, Handle<JSFunction> function) {
|
| + if (function->shared()->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,
|
| // if we are indeed stepping and the callback is subject to debugging.
|
| RUNTIME_FUNCTION(Runtime_DebugPrepareStepInIfStepping) {
|
| DCHECK(args.length() == 1);
|
| Debug* debug = isolate->debug();
|
| - if (debug->in_debug_scope() || !DebugStepInIsActive(debug)) {
|
| - return isolate->heap()->undefined_value();
|
| - }
|
| + if (!DebugStepInIsActive(debug)) return isolate->heap()->undefined_value();
|
|
|
| HandleScope scope(isolate);
|
| CONVERT_ARG_HANDLE_CHECKED(Object, object, 0);
|
| @@ -1654,18 +1689,22 @@
|
| Handle<JSGeneratorObject>::cast(object)->function(), isolate);
|
| }
|
|
|
| - 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();
|
| }
|
|
|
|
|