Class: Capybara::Simulated::StackResolver
- Inherits:
-
Object
- Object
- Capybara::Simulated::StackResolver
- Defined in:
- lib/capybara/simulated/stack_resolver.rb
Overview
Annotates a V8 stack-trace string with original-source positions
from each frame's .map companion file. Resolves once per frame,
caches loaded Sourcemap objects process-wide (built bundles are
fingerprinted; identical URL → identical map).
Frames whose URL has no .map (snapshot stubs, eval'd app inline
scripts) pass through unchanged.
Constant Summary collapse
- FRAME_RE =
Matches
(URL:LINE:COL)inside V8 stack frames. URLs can contain:(e.g.:port), so the URL class includes:and the engine backtracks to find the trailing:digits:digits).file:andcsim-eval:schemes are matched too because both appear in snapshot-warmup frames where the host wraps eval'd content. /\((?<url>(?:https?:\/\/|file:\/\/|csim-eval:)[^\s()]+):(?<line>\d+):(?<col>\d+)\)/- @@maps =
{}
- @@lock =
Mutex.new
Class Method Summary collapse
-
.clear ⇒ Object
Drop the fetched source maps (part of
Browser.clear_http_cache).
Instance Method Summary collapse
-
#annotate(text) ⇒ Object
Returns the input stack/text with
→ source:line:colappended to every frame whose URL maps to a.map. -
#initialize(browser) ⇒ StackResolver
constructor
A new instance of StackResolver.
Constructor Details
#initialize(browser) ⇒ StackResolver
Returns a new instance of StackResolver.
33 34 35 |
# File 'lib/capybara/simulated/stack_resolver.rb', line 33 def initialize(browser) @browser = browser end |
Class Method Details
.clear ⇒ Object
Drop the fetched source maps (part of Browser.clear_http_cache).
29 30 31 |
# File 'lib/capybara/simulated/stack_resolver.rb', line 29 def self.clear @@lock.synchronize { @@maps.clear } end |
Instance Method Details
#annotate(text) ⇒ Object
Returns the input stack/text with → source:line:col appended to
every frame whose URL maps to a .map. If no frame resolves, the
input is returned unchanged.
40 41 42 43 44 45 46 47 48 49 50 |
# File 'lib/capybara/simulated/stack_resolver.rb', line 40 def annotate(text) return text unless text.is_a?(String) && !text.empty? text.gsub(FRAME_RE) { m = ::Regexp.last_match url = m[:url] line = m[:line].to_i col = m[:col].to_i resolved = resolve(url, line, col) resolved ? "#{m[0]} → #{resolved}" : m[0] } end |