Class: SourceMap::Map

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/source_map/map.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(mappings = [], filename = nil) ⇒ Map

Returns a new instance of Map.



78
79
80
# File 'lib/source_map/map.rb', line 78

def initialize(mappings = [], filename = nil)
  @mappings, @filename = mappings, filename
end

Instance Attribute Details

#filenameObject (readonly)

Returns the value of attribute filename.



82
83
84
# File 'lib/source_map/map.rb', line 82

def filename
  @filename
end

Class Method Details

.decode_vlq_mappings(str, sources = [], names = []) ⇒ Object

Internal: Decode VLQ mappings and match up sources and symbol names.

str - VLQ string from ‘mappings’ attribute sources - Array of Strings from ‘sources’ attribute names - Array of Strings from ‘names’ attribute

Returns an Array of Mappings.



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/source_map/map.rb', line 38

def self.decode_vlq_mappings(str, sources = [], names = [])
  mappings = []

  source_id       = 0
  original_line   = 1
  original_column = 0
  name_id         = 0

  VLQ.decode_mappings(str).each_with_index do |group, index|
    generated_column = 0
    generated_line   = index + 1

    group.each do |segment|
      generated_column += segment[0]
      generated = Offset.new(generated_line, generated_column)

      if segment.size >= 4
        source_id        += segment[1]
        original_line    += segment[2]
        original_column  += segment[3]

        source   = sources[source_id]
        original = Offset.new(original_line, original_column)
      else
        # TODO: Research this case
        next
      end

      if segment[4]
        name_id += segment[4]
        name     = names[name_id]
      end

      mappings << Mapping.new(source, generated, original, name)
    end
  end

  mappings
end

.from_hash(hash) ⇒ Object



22
23
24
25
26
27
28
29
# File 'lib/source_map/map.rb', line 22

def self.from_hash(hash)
  str     = hash['mappings']
  sources = hash['sources']
  names   = hash['names']

  mappings = decode_vlq_mappings(str, sources, names)
  new(mappings, hash['file'])
end

.from_json(json) ⇒ Object



18
19
20
# File 'lib/source_map/map.rb', line 18

def self.from_json(json)
  from_hash JSON.parse(json)
end

Instance Method Details

#+(other) ⇒ Object



112
113
114
115
116
117
118
119
120
121
122
# File 'lib/source_map/map.rb', line 112

def +(other)
  mappings = @mappings.dup
  offset   = line_count + 1
  other.each do |m|
    mappings << Mapping.new(
      m.source, m.generated + offset,
      m.original, m.name
    )
  end
  self.class.new(mappings)
end

#[](i) ⇒ Object



92
93
94
# File 'lib/source_map/map.rb', line 92

def [](i)
  @mappings[i]
end

#as_jsonObject



160
161
162
163
164
165
166
167
168
169
# File 'lib/source_map/map.rb', line 160

def as_json
  {
    "version"   => 3,
    "file"      => filename,
    "lineCount" => line_count,
    "mappings"  => to_s,
    "sources"   => sources,
    "names"     => names
  }
end

#bsearch(offset, from = 0, to = size - 1) ⇒ Object



140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# File 'lib/source_map/map.rb', line 140

def bsearch(offset, from = 0, to = size - 1)
  mid = (from + to) / 2

  # We haven't found a match
  if from > to
    return from < 1 ? nil : self[from-1]
  end

  # We found an exact match
  if offset == self[mid].generated
    self[mid]

  # We need to filter more
  elsif offset < self[mid].generated
    bsearch(offset, from, mid - 1)
  elsif offset > self[mid].generated
    bsearch(offset, mid + 1, to)
  end
end

#each(&block) ⇒ Object



96
97
98
# File 'lib/source_map/map.rb', line 96

def each(&block)
  @mappings.each(&block)
end

#line_countObject



84
85
86
# File 'lib/source_map/map.rb', line 84

def line_count
  @line_count ||= @mappings.any? ? @mappings.last.generated.line : 0
end

#namesObject



108
109
110
# File 'lib/source_map/map.rb', line 108

def names
  @names ||= @mappings.map(&:name).uniq.compact
end

#sizeObject



88
89
90
# File 'lib/source_map/map.rb', line 88

def size
  @mappings.size
end

#sourcesObject



104
105
106
# File 'lib/source_map/map.rb', line 104

def sources
  @sources ||= @mappings.map(&:source).uniq.compact
end

#to_sObject



100
101
102
# File 'lib/source_map/map.rb', line 100

def to_s
  @string ||= build_vlq_string
end

#|(other) ⇒ Object



124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/source_map/map.rb', line 124

def |(other)
  mappings = []

  other.each do |m|
    om = bsearch(m.original)
    next unless om

    mappings << Mapping.new(
      om.source, m.generated,
      om.original, om.name
    )
  end

  self.class.new(mappings, other.filename)
end