opal 0.6.3 → 0.7.0.beta1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (221) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +0 -1
  3. data/.spectator +2 -0
  4. data/.spectator-mspec +3 -0
  5. data/.travis.yml +8 -11
  6. data/CHANGELOG.md +33 -0
  7. data/CONTRIBUTING.md +8 -43
  8. data/Gemfile +15 -4
  9. data/Guardfile +77 -0
  10. data/README.md +15 -9
  11. data/Rakefile +36 -12
  12. data/benchmarks/operators.rb +11 -0
  13. data/bin/opal +10 -13
  14. data/bin/opal-build +4 -4
  15. data/bin/opal-mspec +10 -0
  16. data/bin/opal-repl +4 -3
  17. data/examples/sinatra/Gemfile +1 -1
  18. data/examples/sinatra/config.ru +3 -3
  19. data/lib/mspec/opal/main.rb.erb +2 -2
  20. data/lib/mspec/opal/rake_task.rb +31 -24
  21. data/lib/mspec/opal/runner.rb +18 -1
  22. data/lib/mspec/opal/sprockets.js +17 -0
  23. data/lib/opal.rb +1 -34
  24. data/lib/opal/builder.rb +92 -58
  25. data/lib/opal/builder_processors.rb +165 -0
  26. data/lib/opal/cli.rb +85 -144
  27. data/lib/opal/cli_options.rb +136 -90
  28. data/lib/opal/cli_runners.rb +10 -0
  29. data/lib/opal/cli_runners/nodejs.rb +56 -0
  30. data/lib/opal/cli_runners/phantom.js +35 -0
  31. data/lib/opal/cli_runners/phantomjs.rb +28 -0
  32. data/lib/opal/cli_runners/server.rb +54 -0
  33. data/lib/opal/compiler.rb +35 -16
  34. data/lib/opal/erb.rb +29 -15
  35. data/lib/opal/hike_path_finder.rb +18 -0
  36. data/lib/opal/nodes.rb +1 -0
  37. data/lib/opal/nodes/call.rb +107 -26
  38. data/lib/opal/nodes/call_special.rb +31 -6
  39. data/lib/opal/nodes/class.rb +2 -2
  40. data/lib/opal/nodes/constants.rb +5 -20
  41. data/lib/opal/nodes/def.rb +4 -4
  42. data/lib/opal/nodes/defined.rb +3 -3
  43. data/lib/opal/nodes/definitions.rb +1 -1
  44. data/lib/opal/nodes/for.rb +35 -0
  45. data/lib/opal/nodes/helpers.rb +2 -2
  46. data/lib/opal/nodes/iter.rb +3 -3
  47. data/lib/opal/nodes/literal.rb +10 -2
  48. data/lib/opal/nodes/masgn.rb +2 -2
  49. data/lib/opal/nodes/module.rb +2 -2
  50. data/lib/opal/nodes/scope.rb +1 -0
  51. data/lib/opal/nodes/singleton_class.rb +2 -2
  52. data/lib/opal/nodes/super.rb +2 -2
  53. data/lib/opal/nodes/top.rb +30 -3
  54. data/lib/opal/parser.rb +15 -1
  55. data/lib/opal/parser/grammar.rb +2571 -2452
  56. data/lib/opal/parser/grammar.y +37 -5
  57. data/lib/opal/parser/keywords.rb +2 -0
  58. data/lib/opal/parser/lexer.rb +21 -11
  59. data/lib/opal/path_reader.rb +28 -0
  60. data/lib/opal/paths.rb +38 -0
  61. data/lib/opal/source_map.rb +32 -15
  62. data/lib/opal/sprockets/environment.rb +9 -2
  63. data/lib/opal/sprockets/erb.rb +1 -2
  64. data/lib/opal/sprockets/path_reader.rb +34 -0
  65. data/lib/opal/sprockets/processor.rb +40 -39
  66. data/lib/opal/sprockets/server.rb +47 -33
  67. data/lib/opal/version.rb +1 -1
  68. data/opal.gemspec +10 -5
  69. data/opal/README.md +6 -0
  70. data/opal/corelib/array.rb +36 -4
  71. data/opal/corelib/array/inheritance.rb +6 -6
  72. data/opal/corelib/basic_object.rb +9 -9
  73. data/opal/corelib/boolean.rb +1 -1
  74. data/opal/corelib/class.rb +12 -12
  75. data/opal/corelib/dir.rb +20 -0
  76. data/opal/corelib/enumerable.rb +42 -42
  77. data/opal/corelib/enumerator.rb +1 -1
  78. data/opal/corelib/error.rb +2 -2
  79. data/opal/corelib/file.rb +56 -0
  80. data/opal/corelib/hash.rb +5 -5
  81. data/opal/corelib/helpers.rb +3 -3
  82. data/opal/corelib/io.rb +13 -10
  83. data/opal/corelib/kernel.rb +44 -68
  84. data/opal/corelib/method.rb +1 -1
  85. data/opal/corelib/module.rb +89 -114
  86. data/opal/corelib/nil_class.rb +1 -1
  87. data/opal/corelib/numeric.rb +27 -23
  88. data/opal/corelib/proc.rb +5 -5
  89. data/opal/corelib/range.rb +8 -4
  90. data/opal/corelib/regexp.rb +5 -5
  91. data/opal/corelib/runtime.js +589 -272
  92. data/opal/corelib/string.rb +52 -37
  93. data/opal/corelib/string/inheritance.rb +5 -5
  94. data/opal/corelib/time.rb +102 -52
  95. data/opal/corelib/variables.rb +3 -3
  96. data/opal/opal.rb +2 -0
  97. data/package.json +9 -0
  98. data/spec/filters/bugs/array.rb +0 -6
  99. data/spec/filters/bugs/language.rb +4 -0
  100. data/spec/filters/bugs/numeric.rb +7 -6
  101. data/spec/filters/bugs/opal.rb +2 -0
  102. data/spec/filters/bugs/regexp.rb +4 -0
  103. data/spec/filters/bugs/string.rb +0 -7
  104. data/spec/filters/bugs/stringscanner.rb +4 -1
  105. data/spec/filters/unsupported/private_methods.rb +2 -0
  106. data/spec/lib/builder_processors_spec.rb +27 -0
  107. data/spec/lib/builder_spec.rb +66 -0
  108. data/spec/{cli → lib}/cli_spec.rb +60 -5
  109. data/spec/{cli → lib}/compiler_spec.rb +66 -5
  110. data/spec/{cli → lib}/dependency_resolver_spec.rb +1 -1
  111. data/spec/lib/fixtures/no_requires.rb +1 -0
  112. data/spec/{cli → lib}/fixtures/opal_file.rb +0 -0
  113. data/spec/lib/fixtures/require_tree_test.rb +3 -0
  114. data/spec/lib/fixtures/required_tree_test/required_file1.rb +1 -0
  115. data/spec/lib/fixtures/required_tree_test/required_file2.rb +1 -0
  116. data/spec/lib/fixtures/requires.rb +7 -0
  117. data/spec/{cli → lib}/fixtures/sprockets_file.js.rb +0 -0
  118. data/spec/lib/fixtures/sprockets_require_tree_test.rb +3 -0
  119. data/spec/lib/hike_path_finder_spec.rb +23 -0
  120. data/spec/{cli → lib}/lexer_spec.rb +1 -1
  121. data/spec/{cli → lib}/parser/alias_spec.rb +1 -1
  122. data/spec/{cli → lib}/parser/and_spec.rb +1 -1
  123. data/spec/{cli → lib}/parser/attrasgn_spec.rb +1 -1
  124. data/spec/{cli → lib}/parser/begin_spec.rb +1 -1
  125. data/spec/{cli → lib}/parser/block_spec.rb +1 -1
  126. data/spec/{cli → lib}/parser/break_spec.rb +1 -1
  127. data/spec/{cli → lib}/parser/call_spec.rb +1 -1
  128. data/spec/{cli → lib}/parser/class_spec.rb +1 -1
  129. data/spec/{cli → lib}/parser/comments_spec.rb +1 -1
  130. data/spec/{cli → lib}/parser/def_spec.rb +1 -1
  131. data/spec/{cli → lib}/parser/if_spec.rb +1 -1
  132. data/spec/{cli → lib}/parser/iter_spec.rb +1 -1
  133. data/spec/{cli → lib}/parser/lambda_spec.rb +1 -1
  134. data/spec/{cli → lib}/parser/literal_spec.rb +1 -1
  135. data/spec/{cli → lib}/parser/masgn_spec.rb +1 -1
  136. data/spec/{cli → lib}/parser/module_spec.rb +1 -1
  137. data/spec/{cli → lib}/parser/not_spec.rb +1 -1
  138. data/spec/{cli → lib}/parser/op_asgn1_spec.rb +1 -1
  139. data/spec/{cli → lib}/parser/op_asgn2_spec.rb +1 -1
  140. data/spec/{cli → lib}/parser/or_spec.rb +1 -1
  141. data/spec/{cli → lib}/parser/return_spec.rb +1 -1
  142. data/spec/{cli → lib}/parser/sclass_spec.rb +1 -1
  143. data/spec/{cli → lib}/parser/string_spec.rb +8 -1
  144. data/spec/{cli → lib}/parser/super_spec.rb +1 -1
  145. data/spec/lib/parser/unary_spec.rb +48 -0
  146. data/spec/{cli → lib}/parser/undef_spec.rb +1 -1
  147. data/spec/{cli → lib}/parser/unless_spec.rb +1 -1
  148. data/spec/{cli → lib}/parser/variables_spec.rb +1 -1
  149. data/spec/{cli → lib}/parser/while_spec.rb +1 -1
  150. data/spec/{cli → lib}/parser/yield_spec.rb +1 -1
  151. data/spec/lib/path_reader_spec.rb +24 -0
  152. data/spec/lib/shared/path_finder_shared.rb +19 -0
  153. data/spec/lib/shared/path_reader_shared.rb +31 -0
  154. data/spec/lib/spec_helper.rb +9 -0
  155. data/spec/lib/sprockets/environment_spec.rb +30 -0
  156. data/spec/{cli → lib}/sprockets/erb_spec.rb +1 -1
  157. data/spec/lib/sprockets/path_reader_spec.rb +25 -0
  158. data/spec/{cli → lib}/sprockets/processor_spec.rb +9 -2
  159. data/spec/lib/sprockets/server_spec.rb +20 -0
  160. data/spec/opal/compiler/irb_spec.rb +11 -11
  161. data/spec/opal/core/fixtures/require_tree_files/file 1.rb +1 -0
  162. data/spec/opal/core/fixtures/require_tree_files/file 2.rb +1 -0
  163. data/spec/opal/core/fixtures/require_tree_files/file 3.rb +1 -0
  164. data/spec/opal/core/fixtures/require_tree_files/file 4.rb +1 -0
  165. data/spec/opal/core/fixtures/require_tree_files/file 5.rb +1 -0
  166. data/spec/opal/core/kernel/require_tree_spec.rb +7 -0
  167. data/spec/opal/core/kernel/respond_to_spec.rb +2 -2
  168. data/spec/opal/core/runtime/method_missing_spec.rb +19 -0
  169. data/spec/opal/core/source_map_spec.rb +2 -2
  170. data/spec/opal/core/string_spec.rb +11 -0
  171. data/spec/opal/stdlib/erb/erb_spec.rb +0 -1
  172. data/spec/opal/stdlib/thread/mutex_spec.rb +40 -0
  173. data/spec/opal/stdlib/thread/thread_queue_spec.rb +32 -0
  174. data/spec/opal/stdlib/thread/thread_spec.rb +60 -0
  175. data/spec/rubyspecs +54 -11
  176. data/spec/spec_helper.rb +18 -3
  177. data/spec/support/mspec_rspec_adapter.rb +33 -0
  178. data/spec/{cli/spec_helper.rb → support/parser_helpers.rb} +10 -10
  179. data/stdlib/README.md +3 -0
  180. data/stdlib/benchmark.rb +10 -0
  181. data/stdlib/date.rb +2 -2
  182. data/stdlib/dir.rb +1 -5
  183. data/stdlib/file.rb +1 -7
  184. data/stdlib/json.rb +10 -1
  185. data/stdlib/native.rb +5 -5
  186. data/stdlib/nodejs.rb +5 -0
  187. data/stdlib/nodejs/dir.rb +13 -0
  188. data/stdlib/nodejs/file.rb +98 -0
  189. data/stdlib/nodejs/fileutils.rb +26 -0
  190. data/stdlib/nodejs/io.rb +2 -0
  191. data/stdlib/nodejs/irb.rb +45 -0
  192. data/stdlib/nodejs/process.rb +16 -0
  193. data/stdlib/nodejs/require.rb +32 -0
  194. data/stdlib/nodejs/rubygems.rb +68 -0
  195. data/stdlib/nodejs/runtime.rb +25 -0
  196. data/stdlib/nodejs/yaml.rb +11 -0
  197. data/stdlib/opal-parser.rb +1 -2
  198. data/stdlib/opal-source-maps.rb +2 -0
  199. data/stdlib/phantomjs.rb +8 -0
  200. data/stdlib/process.rb +10 -0
  201. data/stdlib/promise.rb +12 -4
  202. data/stdlib/set.rb +27 -0
  203. data/stdlib/source_map.rb +5 -63
  204. data/stdlib/source_map/map.rb +220 -0
  205. data/stdlib/source_map/mapping.rb +26 -0
  206. data/stdlib/source_map/offset.rb +88 -0
  207. data/stdlib/source_map/version.rb +3 -0
  208. data/stdlib/source_map/vlq.rb +77 -101
  209. data/stdlib/sourcemap.rb +1 -0
  210. data/stdlib/strscan.rb +7 -1
  211. data/stdlib/template.rb +1 -1
  212. data/stdlib/thread.rb +147 -7
  213. metadata +238 -104
  214. data/lib/mspec/opal/mspec_fixes.rb +0 -87
  215. data/spec/cli/sprockets/environment_spec.rb +0 -14
  216. data/spec/filters/bugs/symbol.rb +0 -5
  217. data/spec/opal/core/kernel/warn_spec.rb +0 -83
  218. data/spec/opal/core/language/numbers_spec.rb +0 -60
  219. data/stdlib/opal-source-maps.js.erb +0 -2
  220. data/stdlib/source_map/generator.rb +0 -251
  221. data/stdlib/source_map/parser.rb +0 -102
@@ -0,0 +1,68 @@
1
+ require 'json'
2
+
3
+ module Gem
4
+ class Install
5
+ def initialize(name, version)
6
+ @name = name
7
+ @version = version
8
+ end
9
+
10
+ def version
11
+ @version ||= latest_version(name)
12
+ end
13
+
14
+ def latest_version(name)
15
+ command = curl("https://rubygems.org/api/v1/versions/#{name}.json")
16
+ versions = JSON.parse system(command)
17
+ versions.first['number']
18
+ end
19
+
20
+ def full_name
21
+ "#{name}-#{version}"
22
+ end
23
+
24
+ def gem_home
25
+ ENV['HOME']+'/.opal-node/opal-gems/#{RUBY_ENGINE_VERSION}'
26
+ end
27
+
28
+ def gems_dir
29
+ File.join(gem_home, :gems)
30
+ end
31
+
32
+ def specs_dir
33
+ File.join(gem_home, :specs)
34
+ end
35
+
36
+ def perform
37
+ gem_dir = File.join(gems_dir, full_name)
38
+ spec_dir = File.join(specs_dir, full_name+'.yml')
39
+ system "mkdir -p #{gem_dir} #{spec_dir}"
40
+
41
+ Dir.chdir gem_dir do
42
+ system curl("https://rubygems.org/downloads/#{name}-#{version}.gem") + '| tar -xv'
43
+ system "gunzip metadata.gz --stdout > #{specs_dir}/#{full_name}.yml"
44
+ system "gunzip data.tar.gz"
45
+ system "tar -xvf data.tar"
46
+ end
47
+ end
48
+
49
+ def curl url
50
+ "curl -L #{url}"
51
+ end
52
+ end
53
+ end
54
+
55
+ command = ARGV.shift
56
+ case command
57
+ when 'install'
58
+ name = ARGV.shift
59
+ if ARGV.include? '-v'
60
+ version = ARGV[ ARGV.index('-v')+1 ]
61
+ else
62
+ version = nil
63
+ end
64
+ install = Gem::Install.new(name, version)
65
+ install.perform
66
+ else
67
+ raise NotImplementedError, "sorry, the #{command.inspect} is not implemented."
68
+ end
@@ -0,0 +1,25 @@
1
+ %x{
2
+ // Generated by CoffeeScript 1.6.3
3
+ (function() {
4
+ var OpalNode, extensions, fs, parser, parserFile, source, sourceFile, vm, __path__;
5
+ fs = require('fs');
6
+ __path__ = require('path');
7
+ vm = require('vm');
8
+ // vm.runInThisContext(parser, parserFile);
9
+ OpalNode = (function() {
10
+ function OpalNode() {}
11
+ OpalNode.node_require = require;
12
+ return OpalNode;
13
+ })();
14
+
15
+ global.OpalNode = OpalNode;
16
+
17
+ }).call(this);
18
+ }
19
+
20
+ module NodeJS
21
+ def self.require name
22
+ `OpalNode.node_require(#{name})`
23
+ end
24
+ end
25
+
@@ -0,0 +1,11 @@
1
+ require 'native'
2
+
3
+ module YAML
4
+ `var __yaml__ = OpalNode.node_require('js-yaml')`
5
+
6
+ def self.load_path path
7
+ loaded = `__yaml__.yaml.safeLoad(#{File.__fs__}.readFileSync(#{path}, 'utf8'))`
8
+ loaded = Hash.new(loaded) if native?(loaded)
9
+ loaded
10
+ end
11
+ end
@@ -1,11 +1,10 @@
1
1
  require 'opal/compiler'
2
- require 'opal/builder'
3
2
  require 'opal/erb'
4
3
  require 'opal/version'
5
4
 
6
5
  module Kernel
7
6
  def eval(str)
8
- code = Opal.compile str
7
+ code = Opal.compile str, file: '(eval)'
9
8
  `eval(#{code})`
10
9
  end
11
10
 
@@ -0,0 +1,2 @@
1
+ require 'source_map'
2
+ require 'opal/source_map'
@@ -0,0 +1,8 @@
1
+ module Kernel
2
+ def exit status = 0
3
+ `callPhantom(['exit', status]);`
4
+ end
5
+ end
6
+
7
+ STDOUT.write_proc = `function(str){callPhantom(['stdout', str])}`
8
+ STDERR.write_proc = `function(str){callPhantom(['stderr', str])}`
data/stdlib/process.rb ADDED
@@ -0,0 +1,10 @@
1
+ class Process
2
+ def self.pid
3
+ 0
4
+ end
5
+ end
6
+
7
+ class Signal
8
+ def self.trap(*)
9
+ end
10
+ end
data/stdlib/promise.rb CHANGED
@@ -174,8 +174,8 @@ class Promise
174
174
  alias finally always
175
175
  alias ensure always
176
176
 
177
- def trace(&block)
178
- self ^ Trace.new(block)
177
+ def trace(depth = nil, &block)
178
+ self ^ Trace.new(depth, block)
179
179
  end
180
180
 
181
181
  def inspect
@@ -209,9 +209,17 @@ class Promise
209
209
  end
210
210
  end
211
211
 
212
- def initialize(block)
212
+ def initialize(depth, block)
213
+ @depth = depth
214
+
213
215
  super -> {
214
- block.call(*Trace.it(self).reverse)
216
+ trace = Trace.it(self).reverse
217
+
218
+ if depth && depth <= trace.length
219
+ trace.shift(trace.length - depth)
220
+ end
221
+
222
+ block.call(*trace)
215
223
  }
216
224
  end
217
225
  end
data/stdlib/set.rb CHANGED
@@ -9,6 +9,7 @@ class Set
9
9
  @hash = Hash.new
10
10
 
11
11
  return if enum.nil?
12
+ raise ArgumentError, 'value must be enumerable' unless Enumerable === enum
12
13
 
13
14
  if block
14
15
  do_with_enum(enum) { |o| add(block[o]) }
@@ -17,6 +18,10 @@ class Set
17
18
  end
18
19
  end
19
20
 
21
+ def inspect
22
+ "#<Set: {#{to_a.join(',')}}>"
23
+ end
24
+
20
25
  def ==(other)
21
26
  if self.equal?(other)
22
27
  true
@@ -35,6 +40,28 @@ class Set
35
40
  end
36
41
  alias << add
37
42
 
43
+ def delete(o)
44
+ @hash.delete(o)
45
+ self
46
+ end
47
+
48
+ def delete?(o)
49
+ if include?(o)
50
+ delete(o)
51
+ self
52
+ else
53
+ nil
54
+ end
55
+ end
56
+
57
+ def delete_if
58
+ block_given? or return enum_for(__method__)
59
+ # @hash.delete_if should be faster, but using it breaks the order
60
+ # of enumeration in subclasses.
61
+ select { |o| yield o }.each { |o| @hash.delete(o) }
62
+ self
63
+ end
64
+
38
65
  def add?(o)
39
66
  if include?(o)
40
67
  nil
data/stdlib/source_map.rb CHANGED
@@ -1,63 +1,5 @@
1
- require 'json'
2
-
3
- require 'source_map/vlq.rb'
4
- require 'source_map/generator.rb'
5
- require 'source_map/parser.rb'
6
-
7
- class SourceMap
8
- include SourceMap::Generator
9
- include SourceMap::Parser
10
-
11
- # Create a new blank SourceMap
12
- #
13
- # Options may include:
14
- #
15
- # :file => String # See {#file}
16
- # :source_root => String # See {#source_root}
17
- # :generated_output => IO # See {#generated_output}
18
- #
19
- # :sources => Array[String] # See {#sources}
20
- # :names => Array[String] # See {#names}
21
- #
22
- # :version => 3 # Which version of SourceMap to use (only 3 is allowed)
23
- #
24
- def initialize(opts={})
25
- unless (remain = opts.keys - [:generated_output, :file, :source_root, :sources, :names, :version]).empty?
26
- raise ArgumentError, "Unsupported options to SourceMap.new: #{remain.inspect}"
27
- end
28
- self.generated_output = opts[:generated_output]
29
- self.file = opts[:file] || ''
30
- self.source_root = opts[:source_root] || ''
31
- self.version = opts[:version] || 3
32
- self.sources = opts[:sources] || []
33
- self.names = opts[:names] || []
34
- self.mappings = []
35
- raise "version #{opts[:version]} not supported" if version != 3
36
- end
37
-
38
- # The name of the file containing the code that this SourceMap describes.
39
- # (default "")
40
- attr_accessor :file
41
-
42
- # The URL/directory that contains the original source files.
43
- #
44
- # This is prefixed to the entries in ['sources']
45
- # (default "")
46
- attr_accessor :source_root
47
-
48
- # The version of the SourceMap spec we're using.
49
- # (default 3)
50
- attr_accessor :version
51
-
52
- # The list of sources (used during parsing/generating)
53
- # These are relative to the source_root.
54
- # (default [])
55
- attr_accessor :sources
56
-
57
- # A list of names (used during parsing/generating)
58
- # (default [])
59
- attr_accessor :names
60
-
61
- # A list of mapping objects.
62
- attr_accessor :mappings
63
- end
1
+ require 'source_map/map'
2
+ require 'source_map/mapping'
3
+ require 'source_map/offset'
4
+ require 'source_map/version'
5
+ require 'source_map/vlq'
@@ -0,0 +1,220 @@
1
+ require 'json'
2
+
3
+ require 'source_map/offset'
4
+ require 'source_map/mapping'
5
+ require 'source_map/vlq'
6
+
7
+ module SourceMap
8
+ class Map
9
+ include Enumerable
10
+
11
+ def self.from_json(json)
12
+ from_hash JSON.parse(json)
13
+ end
14
+
15
+ def self.from_hash(hash)
16
+ str = hash['mappings']
17
+ sources = hash['sources']
18
+ names = hash['names']
19
+
20
+ mappings = decode_vlq_mappings(str, sources, names)
21
+ new(mappings, hash['file'])
22
+ end
23
+
24
+ # Internal: Decode VLQ mappings and match up sources and symbol names.
25
+ #
26
+ # str - VLQ string from 'mappings' attribute
27
+ # sources - Array of Strings from 'sources' attribute
28
+ # names - Array of Strings from 'names' attribute
29
+ #
30
+ # Returns an Array of Mappings.
31
+ def self.decode_vlq_mappings(str, sources = [], names = [])
32
+ mappings = []
33
+
34
+ source_id = 0
35
+ original_line = 1
36
+ original_column = 0
37
+ name_id = 0
38
+
39
+ VLQ.decode_mappings(str).each_with_index do |group, index|
40
+ generated_column = 0
41
+ generated_line = index + 1
42
+
43
+ group.each do |segment|
44
+ generated_column += segment[0]
45
+ generated = Offset.new(generated_line, generated_column)
46
+
47
+ if segment.size >= 4
48
+ source_id += segment[1]
49
+ original_line += segment[2]
50
+ original_column += segment[3]
51
+
52
+ source = sources[source_id]
53
+ original = Offset.new(original_line, original_column)
54
+ else
55
+ # TODO: Research this case
56
+ next
57
+ end
58
+
59
+ if segment[4]
60
+ name_id += segment[4]
61
+ name = names[name_id]
62
+ end
63
+
64
+ mappings << Mapping.new(source, generated, original, name)
65
+ end
66
+ end
67
+
68
+ mappings
69
+ end
70
+
71
+ def initialize(mappings = [], filename = nil)
72
+ @mappings, @filename = mappings, filename
73
+ end
74
+
75
+ attr_reader :filename
76
+
77
+ def size
78
+ @mappings.size
79
+ end
80
+
81
+ def [](i)
82
+ @mappings[i]
83
+ end
84
+
85
+ def each(&block)
86
+ @mappings.each(&block)
87
+ end
88
+
89
+ def to_s
90
+ @string ||= build_vlq_string
91
+ end
92
+
93
+ def sources
94
+ @sources ||= @mappings.map(&:source).uniq.compact
95
+ end
96
+
97
+ def names
98
+ @names ||= @mappings.map(&:name).uniq.compact
99
+ end
100
+
101
+ def ==(other)
102
+ eql?(other)
103
+ end
104
+
105
+ def eql?(other)
106
+ other.is_a?(self.class) &&
107
+ self.mappings == other.mappings &&
108
+ self.filename == other.filename
109
+ end
110
+
111
+ def +(other)
112
+ mappings = @mappings.dup
113
+ offset = @mappings.any? ? @mappings.last.generated.line+1 : 0
114
+ other.each do |m|
115
+ mappings << Mapping.new(
116
+ m.source, m.generated + offset,
117
+ m.original, m.name
118
+ )
119
+ end
120
+ self.class.new(mappings, other.filename)
121
+ end
122
+
123
+ def |(other)
124
+ return other.dup if self.mappings.empty?
125
+
126
+ mappings = []
127
+
128
+ other.each do |m|
129
+ om = bsearch(m.original)
130
+ next unless om
131
+
132
+ mappings << Mapping.new(
133
+ om.source, m.generated,
134
+ om.original, om.name
135
+ )
136
+ end
137
+
138
+ self.class.new(mappings, other.filename)
139
+ end
140
+
141
+ def bsearch(offset, from = 0, to = size - 1)
142
+ mid = (from + to) / 2
143
+
144
+ # We haven't found a match
145
+ if from > to
146
+ return from < 1 ? nil : self[from-1]
147
+ end
148
+
149
+ # We found an exact match
150
+ if offset == self[mid].generated
151
+ self[mid]
152
+
153
+ # We need to filter more
154
+ elsif offset < self[mid].generated
155
+ bsearch(offset, from, mid - 1)
156
+ elsif offset > self[mid].generated
157
+ bsearch(offset, mid + 1, to)
158
+ end
159
+ end
160
+
161
+ def as_json
162
+ {
163
+ "version" => 3,
164
+ "file" => filename,
165
+ "mappings" => to_s,
166
+ "sources" => sources,
167
+ "names" => names
168
+ }
169
+ end
170
+
171
+ # Public: Get a pretty inspect output for debugging purposes.
172
+ #
173
+ # Returns a String.
174
+ def inspect
175
+ str = "#<#{self.class}"
176
+ str << " filename=#{filename.inspect}" if filename
177
+ str << " mappings=#{mappings.map(&:to_s).inspect}" if mappings.any?
178
+ str << ">"
179
+ str
180
+ end
181
+
182
+ protected
183
+ attr_reader :mappings
184
+
185
+ def build_vlq_string
186
+ source_id = 0
187
+ source_line = 1
188
+ source_column = 0
189
+ name_id = 0
190
+
191
+ by_lines = @mappings.group_by { |m| m.generated.line }
192
+
193
+ sources_index = Hash[sources.each_with_index.to_a]
194
+ names_index = Hash[names.each_with_index.to_a]
195
+
196
+ ary = (1..(by_lines.keys.max || 1)).map do |line|
197
+ generated_column = 0
198
+
199
+ (by_lines[line] || []).map do |mapping|
200
+ group = []
201
+ group << mapping.generated.column - generated_column
202
+ group << sources_index[mapping.source] - source_id
203
+ group << mapping.original.line - source_line
204
+ group << mapping.original.column - source_column
205
+ group << names_index[mapping.name] - name_id if mapping.name
206
+
207
+ generated_column = mapping.generated.column
208
+ source_id = sources_index[mapping.source]
209
+ source_line = mapping.original.line
210
+ source_column = mapping.original.column
211
+ name_id = names_index[mapping.name] if mapping.name
212
+
213
+ group
214
+ end
215
+ end
216
+
217
+ VLQ.encode_mappings(ary)
218
+ end
219
+ end
220
+ end