From 44a8a7d685f25c35da9872da7475e58e00923e28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20Z=C3=BCnd?= Date: Wed, 12 Jan 2022 12:43:40 +0100 Subject: [PATCH] Introduce v8::StackTrace::CurrentScriptNameOrSourceURL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This CL introduces a dedicated API to retrieve the current (w.r.t. the JS stack) script name or sourceURL. Currently, API clients will collect multiple stack traces in increasing sizes to accomplish the same goal. The new method walks the JS stack in the same way as the stack trace collection mechanic but doesn't create/allocate stack info or callsite objects along the way. R=bmeurer@chromium.org, yangguo@chromium.org Doc: https://bit.ly/v8-current-script-name Bug: chromium:1286677 Change-Id: Id53e4f04bf17349d34f3d581bc712b1f4aa055db Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3382818 Reviewed-by: Benedikt Meurer Commit-Queue: Simon Zünd Cr-Commit-Position: refs/heads/main@{#78645} --- include/v8-debug.h | 12 ++++++ src/api/api.cc | 8 ++++ src/execution/isolate.cc | 41 +++++++++++++++++++++ src/execution/isolate.h | 4 ++ test/cctest/test-api-stack-traces.cc | 55 ++++++++++++++++++++++++++++ 5 files changed, 120 insertions(+) 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