Class: Capybara::Simulated::Sourcemap

Inherits:
Object
  • Object
show all
Defined in:
lib/capybara/simulated/sourcemap.rb

Overview

Minimal source-map v3 decoder. Just enough for the stack-trace rewriter to map ‘<asset URL>:<line>:<col>` back to `<source file>:<line>:<col>` so failing-test traces point at the original TS/JS instead of a 100k-char minified blob.

Not handled:

- `sections` (composite maps) — Vite/Rolldown don't emit them
- `names` lookup — we don't need them for source-only resolution

Defined Under Namespace

Classes: Position

Constant Summary collapse

BASE64_CHARS =
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
BASE64_LOOKUP =
BASE64_CHARS.each_char.with_index.to_h.freeze

Instance Method Summary collapse

Constructor Details

#initialize(json) ⇒ Sourcemap

Returns a new instance of Sourcemap.



21
22
23
24
25
# File 'lib/capybara/simulated/sourcemap.rb', line 21

def initialize(json)
  @sources = (json['sources'] || []).map(&:to_s)
  @source_root = json['sourceRoot'].to_s
  @segments_by_line = parse_mappings(json['mappings'].to_s)
end

Instance Method Details

#resolve(line, column) ⇒ Object

Returns the nearest mapping at-or-before (line, column). Line/col are 1-based to match V8’s stack-trace convention.



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/capybara/simulated/sourcemap.rb', line 29

def resolve(line, column)
  return nil if line < 1
  row = @segments_by_line[line - 1]
  return nil unless row && !row.empty?
  # Per-line row is a flat Integer array of stride 4: [gen_col,
  # source_idx, src_line, src_col, ...]. `bsearch_index` finds the
  # first segment whose gen_col is *strictly greater* than target;
  # the segment before that is the match.
  target = column - 1
  idx = (0...(row.length / 4)).bsearch {|i| row[i * 4] > target }
  match_i = (idx || row.length / 4) - 1
  return nil if match_i < 0
  base = match_i * 4
  source_idx = row[base + 1]
  return nil unless source_idx && @sources[source_idx]
  Position.new(
    source: full_source(@sources[source_idx]),
    line:   row[base + 2] + 1,
    column: row[base + 3] + 1
  )
end