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
@@ -470,11 +470,19 @@ rule
470
470
  result = new_binary_call(val[0], val[1], val[2])
471
471
  }
472
472
  | '-@NUM' tINTEGER tPOW arg
473
+ {
474
+ result = new_call new_binary_call(new_int(val[1]), val[2], val[3]), [:"-@", []], []
475
+ }
473
476
  | '-@NUM' tFLOAT tPOW arg
477
+ {
478
+ result = new_call new_binary_call(new_float(val[1]), val[2], val[3]), [:"-@", []], []
479
+ }
474
480
  | tUPLUS arg
475
481
  {
476
482
  result = new_call val[1], [:"+@", []], []
477
- result = val[1] if [:int, :float].include? val[1].type
483
+ if [:int, :float].include? val[1].type
484
+ result = val[1]
485
+ end
478
486
  }
479
487
  | tUMINUS arg
480
488
  {
@@ -843,15 +851,19 @@ rule
843
851
  {
844
852
  result = s(:case, nil, val[3])
845
853
  }
846
- | kFOR mlhs kIN
854
+ | kFOR for_var kIN
847
855
  {
848
- # ...
856
+ lexer.cond_push 1
857
+ result = lexer.line
849
858
  }
850
859
  expr_value do
851
860
  {
852
- # ...
861
+ lexer.cond_pop
853
862
  }
854
863
  compstmt kEND
864
+ {
865
+ result = s(:for, val[4], val[1], val[7])
866
+ }
855
867
  | kCLASS cpath superclass
856
868
  {
857
869
  # ...
@@ -1130,7 +1142,7 @@ opt_block_args_tail: tCOMMA block_args_tail
1130
1142
  {
1131
1143
  part = s(:when, s(:array, *val[2]), val[4])
1132
1144
  result = [part]
1133
- result.push *val[5] if val[5]
1145
+ result.push(*val[5]) if val[5]
1134
1146
  }
1135
1147
 
1136
1148
  cases: opt_else
@@ -1184,6 +1196,9 @@ opt_block_args_tail: tCOMMA block_args_tail
1184
1196
 
1185
1197
  string: string1
1186
1198
  | string string1
1199
+ {
1200
+ result = str_append val[0], val[1]
1201
+ }
1187
1202
 
1188
1203
  string1: tSTRING_BEG string_contents tSTRING_END
1189
1204
  {
@@ -1343,7 +1358,21 @@ xstring_contents: none
1343
1358
  result = new_float(val[0])
1344
1359
  }
1345
1360
  | '-@NUM' tINTEGER =tLOWEST
1361
+ {
1362
+ result = negate_num(new_int(val[1]))
1363
+ }
1346
1364
  | '-@NUM' tFLOAT =tLOWEST
1365
+ {
1366
+ result = negate_num(new_float(val[1]))
1367
+ }
1368
+ | '+@NUM' tINTEGER =tLOWEST
1369
+ {
1370
+ result = new_int(val[1])
1371
+ }
1372
+ | '+@NUM' tFLOAT =tLOWEST
1373
+ {
1374
+ result = new_float(val[1])
1375
+ }
1347
1376
 
1348
1377
  variable: tIDENTIFIER
1349
1378
  {
@@ -1499,6 +1528,9 @@ xstring_contents: none
1499
1528
  result = val[1]
1500
1529
  }
1501
1530
 
1531
+ for_var: lhs
1532
+ | mlhs
1533
+
1502
1534
  f_marg: f_norm_arg
1503
1535
  {
1504
1536
  result = s(:lasgn, val[0])
@@ -28,7 +28,9 @@ module Opal
28
28
  ["end", [:kEND, :kEND], :expr_end],
29
29
  ["ensure", [:kENSURE, :kENSURE], :expr_beg],
30
30
  ["false", [:kFALSE, :kFALSE], :expr_end],
31
+ ["for", [:kFOR, :kFOR], :expr_beg],
31
32
  ["if", [:kIF, :kIF_MOD], :expr_beg],
33
+ ["in", [:kIN, :kIN], :expr_beg],
32
34
  ["module", [:kMODULE, :kMODULE], :expr_beg],
33
35
  ["nil", [:kNIL, :kNIL], :expr_end],
34
36
  ["next", [:kNEXT, :kNEXT], :expr_mid],
@@ -21,7 +21,7 @@ module Opal
21
21
  STR_SSYM = STR_FUNC_SYMBOL
22
22
  STR_DSYM = STR_FUNC_SYMBOL | STR_FUNC_EXPAND
23
23
 
24
- attr_reader :line
24
+ attr_reader :line, :column
25
25
  attr_reader :scope
26
26
  attr_reader :eof_content
27
27
 
@@ -43,6 +43,9 @@ module Opal
43
43
 
44
44
  @scanner = StringScanner.new(source)
45
45
  @scanner_stack = [@scanner]
46
+
47
+ @case_stmt = nil
48
+ @start_of_lambda = nil
46
49
  end
47
50
 
48
51
  def has_local?(local)
@@ -173,21 +176,24 @@ module Opal
173
176
  def process_numeric
174
177
  @lex_state = :expr_end
175
178
 
176
- if scan(/0b?(0|1|_)+/)
177
- self.yylval = scanner.matched.to_i(2)
178
- return :tINTEGER
179
- elsif scan(/0o?([0-7]|_)+/)
180
- self.yylval = scanner.matched.to_i(8)
181
- return :tINTEGER
182
- elsif scan(/[\d_]+\.[\d_]+\b|[\d_]+(\.[\d_]+)?[eE][-+]?[\d_]+\b/)
179
+ if scan(/[\d_]+\.[\d_]+\b|[\d_]+(\.[\d_]+)?[eE][-+]?[\d_]+\b/) # FLOATS
183
180
  self.yylval = scanner.matched.gsub(/_/, '').to_f
184
181
  return :tFLOAT
185
- elsif scan(/[\d_]+\b/)
182
+ elsif scan(/([^0][\d_]*|0)\b/) # BASE 10
186
183
  self.yylval = scanner.matched.gsub(/_/, '').to_i
187
184
  return :tINTEGER
188
- elsif scan(/0(x|X)(\d|[a-f]|[A-F]|_)+/)
185
+ elsif scan(/0[bB](0|1|_)+/) # BASE 2
186
+ self.yylval = scanner.matched.to_i(2)
187
+ return :tINTEGER
188
+ elsif scan(/0[xX](\d|[a-f]|[A-F]|_)+/) # BASE 16
189
189
  self.yylval = scanner.matched.to_i(16)
190
190
  return :tINTEGER
191
+ elsif scan(/0[oO]?([0-7]|_)+/) # BASE 8
192
+ self.yylval = scanner.matched.to_i(8)
193
+ return :tINTEGER
194
+ elsif scan(/0[dD]([0-9]|_)+/) # BASE 10
195
+ self.yylval = scanner.matched.gsub(/_/, '').to_i
196
+ return :tINTEGER
191
197
  else
192
198
  raise "Lexing error on numeric type: `#{scanner.peek 5}`"
193
199
  end
@@ -1057,7 +1063,11 @@ module Opal
1057
1063
  if beg?
1058
1064
  @lex_state = :expr_mid
1059
1065
  self.yylval = matched
1060
- return utype
1066
+ if scanner.peek(1) =~ /\d/ and
1067
+ return utype == :tUMINUS ? '-@NUM' : '+@NUM'
1068
+ else
1069
+ return utype
1070
+ end
1061
1071
  elsif after_operator?
1062
1072
  @lex_state = :expr_arg
1063
1073
  if scan(/@/)
@@ -0,0 +1,28 @@
1
+ require 'opal/hike_path_finder'
2
+
3
+ module Opal
4
+ class PathReader
5
+ def initialize(file_finder = HikePathFinder.new)
6
+ @file_finder = file_finder
7
+ end
8
+
9
+ def read(path)
10
+ full_path = expand(path)
11
+ return nil if full_path.nil?
12
+ File.read(full_path)
13
+ end
14
+
15
+ def expand(path)
16
+ file_finder.find(path)
17
+ end
18
+
19
+ def paths
20
+ file_finder.paths
21
+ end
22
+
23
+
24
+ private
25
+
26
+ attr_reader :file_finder
27
+ end
28
+ end
data/lib/opal/paths.rb ADDED
@@ -0,0 +1,38 @@
1
+ module Opal
2
+ def self.gem_dir
3
+ File.expand_path('../..', __FILE__.untaint)
4
+ end
5
+
6
+ def self.core_dir
7
+ File.expand_path('../../../opal', __FILE__.untaint)
8
+ end
9
+
10
+ def self.std_dir
11
+ File.expand_path('../../../stdlib', __FILE__.untaint)
12
+ end
13
+
14
+ # Add a file path to opals load path. Any gem containing ruby code that Opal
15
+ # has access to should add a load path through this method. Load paths added
16
+ # here should only be paths which contain code targeted at being compiled by
17
+ # Opal.
18
+ def self.append_path(path)
19
+ paths << path
20
+ end
21
+
22
+ def self.use_gem(gem_name, include_dependecies = true)
23
+ spec = Gem::Specification.find_by_name(gem_name)
24
+
25
+ spec.runtime_dependencies.each do |dependency|
26
+ use_gem dependency.name
27
+ end if include_dependecies
28
+
29
+ spec.require_paths.each do |path|
30
+ Opal.append_path File.join(spec.gem_dir, path)
31
+ end
32
+ end
33
+
34
+ # Private, don't add to these directly (use .append_path instead).
35
+ def self.paths
36
+ @paths ||= [core_dir.untaint, std_dir.untaint, gem_dir.untaint]
37
+ end
38
+ end
@@ -12,29 +12,46 @@ module Opal
12
12
  end
13
13
 
14
14
  def map
15
- @map ||= ::SourceMap.new.tap do |map|
16
- line, column = 1, 0
17
-
18
- @fragments.each do |fragment|
19
- if source_line = fragment.line
20
- map.add_mapping(
21
- :generated_line => line,
22
- :generated_col => column,
23
- :source_line => source_line,
24
- :source_col => fragment.column,
25
- :source => file
15
+ @map ||= begin
16
+ source_file = file+'.rb'
17
+ generated_line, generated_column = 1, 0
18
+
19
+ mappings = @fragments.map do |fragment|
20
+ mapping = nil
21
+ source_line = fragment.line
22
+ source_column = fragment.column
23
+ source_code = fragment.code
24
+
25
+ if source_line and source_column
26
+ source_offset = ::SourceMap::Offset.new(source_line, source_column)
27
+ generated_offset = ::SourceMap::Offset.new(generated_line, generated_column)
28
+
29
+ mapping = ::SourceMap::Mapping.new(
30
+ source_file,
31
+ generated_offset,
32
+ source_offset
26
33
  )
27
34
  end
28
35
 
29
- new_lines = fragment.code.count "\n"
30
- line += new_lines
36
+ new_lines = source_code.count "\n"
37
+ generated_line += new_lines
31
38
 
32
39
  if new_lines > 0
33
- column = fragment.code.size - (fragment.code.rindex("\n") + 1)
40
+ generated_column = source_code.size - (source_code.rindex("\n") + 1)
34
41
  else
35
- column += fragment.code.size
42
+ generated_column += source_code.size
36
43
  end
44
+
45
+ mapping
37
46
  end
47
+
48
+ # Ensure mappings isn't empty: https://github.com/maccman/sourcemap/issues/11
49
+ unless mappings.any?
50
+ zero_offset = ::SourceMap::Offset.new(0,0)
51
+ mappings = [::SourceMap::Mapping.new(source_file,zero_offset,zero_offset)]
52
+ end
53
+
54
+ ::SourceMap::Map.new(mappings.compact)
38
55
  end
39
56
  end
40
57
 
@@ -20,11 +20,18 @@ module Opal
20
20
  class Environment < ::Sprockets::Environment
21
21
  def initialize *args
22
22
  super
23
- Opal.paths.each { |p| append_path p }
23
+ append_opal_paths
24
24
  end
25
25
 
26
26
  def use_gem gem_name
27
- append_path File.join(Gem::Specification.find_by_name(gem_name).gem_dir, 'lib')
27
+ Opal.use_gem gem_name
28
+ append_opal_paths
29
+ end
30
+
31
+ private
32
+
33
+ def append_opal_paths
34
+ Opal.paths.each { |p| append_path p }
28
35
  end
29
36
  end
30
37
  end
@@ -1,6 +1,4 @@
1
- require 'opal'
2
1
  require 'tilt'
3
- require 'opal/erb'
4
2
  require 'sprockets'
5
3
 
6
4
  module Opal
@@ -19,6 +17,7 @@ module Opal
19
17
 
20
18
  def initialize_engine
21
19
  require_template_library 'opal'
20
+ require_template_library 'opal/erb'
22
21
  end
23
22
 
24
23
  def prepare
@@ -0,0 +1,34 @@
1
+ module Opal
2
+ module Sprockets
3
+
4
+ class PathReader
5
+ def initialize(env, context)
6
+ @env ||= env
7
+ @context ||= context
8
+ end
9
+
10
+ def read path
11
+ if path.end_with? '.js'
12
+ context.depend_on_asset(path)
13
+ env[path].to_s
14
+ else
15
+ context.depend_on(path)
16
+ File.read(expand(path))
17
+ end
18
+ rescue ::Sprockets::FileNotFound
19
+ nil
20
+ end
21
+
22
+ def expand path
23
+ env.resolve(path)
24
+ end
25
+
26
+ def paths
27
+ env.paths
28
+ end
29
+
30
+ attr_reader :env, :context
31
+ end
32
+
33
+ end
34
+ end
@@ -1,6 +1,9 @@
1
1
  require 'set'
2
+ require 'tilt'
2
3
  require 'sprockets'
3
4
  require 'opal/version'
5
+ require 'opal/builder'
6
+ require 'opal/sprockets/path_reader'
4
7
 
5
8
  $OPAL_SOURCE_MAPS = {}
6
9
 
@@ -11,12 +14,12 @@ module Opal
11
14
  # which effect how certain ruby features are handled:
12
15
  #
13
16
  # * method_missing_enabled [true by default]
14
- # * optimized_operators_enabled [true by default]
15
17
  # * arity_check_enabled [false by default]
16
18
  # * const_missing_enabled [true by default]
17
- # * dynamic_require_severity [true by default]
19
+ # * dynamic_require_severity [:error by default]
18
20
  # * source_map_enabled [true by default]
19
21
  # * irb_enabled [false by default]
22
+ # * inline_operators_enabled [false by default]
20
23
  #
21
24
  class Processor < Tilt::Template
22
25
  # vvv BOILERPLATE vvv
@@ -46,6 +49,9 @@ module Opal
46
49
  attr_accessor :dynamic_require_severity
47
50
  attr_accessor :source_map_enabled
48
51
  attr_accessor :irb_enabled
52
+ attr_accessor :inline_operators_enabled
53
+
54
+ attr_accessor :source_map_register
49
55
  end
50
56
 
51
57
  self.method_missing_enabled = true
@@ -55,63 +61,58 @@ module Opal
55
61
  self.source_map_enabled = true
56
62
  self.irb_enabled = false
57
63
 
58
- def self.stub_file(name)
59
- stubbed_files << name.to_s
60
- end
64
+ self.source_map_register = $OPAL_SOURCE_MAPS
61
65
 
62
- def self.stubbed_files
63
- @stubbed_files ||= Set.new
64
- end
65
66
 
66
67
  def evaluate(context, locals, &block)
67
- options = {
68
- :method_missing => self.class.method_missing_enabled,
69
- :arity_check => self.class.arity_check_enabled,
70
- :const_missing => self.class.const_missing_enabled,
71
- :dynamic_require_severity => self.class.dynamic_require_severity,
72
- :irb => self.class.irb_enabled,
73
- :file => context.logical_path,
74
- }
68
+ return Opal.compile data unless context.is_a? ::Sprockets::Context
75
69
 
76
- compiler = Opal::Compiler.new
77
- result = compiler.compile data, options
70
+ path = context.logical_path
71
+ prerequired = []
78
72
 
79
- compiler.requires.each do |r|
80
- next if stubbed_file? r
81
- path = find_opal_require context.environment, r
82
- context.require_asset path
83
- end
73
+ builder = self.class.new_builder(context)
74
+ result = builder.build_str(data, path, :prerequired => prerequired)
84
75
 
85
76
  if self.class.source_map_enabled
86
- $OPAL_SOURCE_MAPS[context.pathname] = compiler.source_map(source_file_url(context)).to_s
87
- "#{result}\n//# sourceMappingURL=#{source_map_url(context)}\n"
77
+ register_source_map(context.logical_path, result.source_map.to_s)
78
+ "#{result.to_s}\n//# sourceMappingURL=#{context.logical_path}.map\n"
88
79
  else
89
- result
80
+ result.to_s
90
81
  end
91
82
  end
92
83
 
93
- def source_map_url(context)
94
- "#{prefix}/#{context.logical_path}.js.map"
84
+ def register_source_map path, map_contents
85
+ self.class.source_map_register[path] = map_contents
95
86
  end
96
87
 
97
- def source_file_url(context)
98
- "#{prefix}/#{context.logical_path.to_s}"
88
+ def self.stubbed_files
89
+ @stubbed_files ||= []
99
90
  end
100
91
 
101
- def prefix
102
- "/__opal_source_maps__"
92
+ def self.stub_file(name)
93
+ stubbed_files << name.to_s
103
94
  end
104
95
 
105
- def stubbed_file?(name)
106
- self.class.stubbed_files.include? name
96
+ def stubbed_files
97
+ self.class.stubbed_files
107
98
  end
108
99
 
109
- def find_opal_require(environment, r)
110
- path = environment.paths.find do |p|
111
- File.exist?(File.join(p, "#{r}.rb"))
112
- end
100
+ def self.new_builder(context)
101
+ compiler_options = {
102
+ :method_missing => method_missing_enabled,
103
+ :arity_check => arity_check_enabled,
104
+ :const_missing => const_missing_enabled,
105
+ :dynamic_require_severity => dynamic_require_severity,
106
+ :irb => irb_enabled,
107
+ :inline_operators => inline_operators_enabled
108
+ }
113
109
 
114
- path ? File.join(path, "#{r}.rb") : r
110
+ path_reader = ::Opal::Sprockets::PathReader.new(context.environment, context)
111
+ return Builder.new(
112
+ compiler_options: compiler_options,
113
+ stubs: stubbed_files,
114
+ path_reader: path_reader
115
+ )
115
116
  end
116
117
  end
117
118
  end