diff --git a/include/v8-debug.h b/include/v8-debug.h index d7cf129999..52255f3700 100644 --- a/include/v8-debug.h +++ b/include/v8-debug.h @@ -149,6 +149,18 @@ class V8_EXPORT StackTrace { */ static Local CurrentStackTrace( Isolate* isolate, int frame_limit, StackTraceOptions options = kDetailed); + + /** + * Returns the first valid script name or source URL starting at the top of + * the JS stack. The returned string is either an empty handle if no script + * name/url was found or a non-zero-length string. + * + * This method is equivalent to calling StackTrace::CurrentStackTrace and + * walking the resulting frames from the beginning until a non-empty script + * name/url is found. The difference is that this method won't allocate + * a stack trace. + */ + static Local CurrentScriptNameOrSourceURL(Isolate* isolate); }; } // namespace v8 diff --git a/src/api/api.cc b/src/api/api.cc index f2ac48f7fd..ff8febe4ae 100644 --- a/src/api/api.cc +++ b/src/api/api.cc @@ -3248,6 +3248,14 @@ Local StackTrace::CurrentStackTrace(Isolate* isolate, return Utils::StackTraceToLocal(stackTrace); } +Local StackTrace::CurrentScriptNameOrSourceURL(Isolate* v8_isolate) { + i::Isolate* isolate = reinterpret_cast(v8_isolate); + ENTER_V8_NO_SCRIPT_NO_EXCEPTION(isolate); + i::Handle name_or_source_url = + isolate->CurrentScriptNameOrSourceURL(); + return Utils::ToLocal(name_or_source_url); +} + // --- S t a c k F r a m e --- Location StackFrame::GetLocation() const { diff --git a/src/execution/isolate.cc b/src/execution/isolate.cc index 6f6e03f084..777a448471 100644 --- a/src/execution/isolate.cc +++ b/src/execution/isolate.cc @@ -1338,6 +1338,47 @@ Handle Isolate::CaptureDetailedStackTrace( return stack_trace; } +namespace { + +class CurrentScriptNameStackVisitor { + public: + explicit CurrentScriptNameStackVisitor(Isolate* isolate) + : isolate_(isolate) {} + + bool Visit(FrameSummary& summary) { + // Skip frames that aren't subject to debugging. Keep this in sync with + // StackFrameBuilder::Visit so both visitors visit the same frames. + if (!summary.is_subject_to_debugging()) return true; + + // Frames that are subject to debugging always have a valid script object. + Handle