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
data/bin/opal-build CHANGED
@@ -19,9 +19,9 @@ module Opal
19
19
  end
20
20
 
21
21
  opts.on('-g', '--gem GEM_NAME', String,
22
- 'Adds the specified GEM_NAME to Opal\'s load path.',
23
- 'E.g.: opal-build --require opal-browser browser`',
24
- 'Will build browser.rb from the Opal gem opal-browser') do |g|
22
+ 'Adds the specified GEM_NAME lib dir to Opal\'s load path.',
23
+ 'E.g.: opal-build --gem erubis -- erubis`',
24
+ 'Will build erubis.rb from the regular "erubis" gem') do |g|
25
25
  options[:gems] ||= []
26
26
  options[:gems] << g
27
27
  end
@@ -54,7 +54,7 @@ option_parser = Opal::BuilderOptions.new
54
54
  option_parser.parse!
55
55
 
56
56
  if ARGV.empty?
57
- puts options
57
+ puts option_parser
58
58
  else
59
59
  require 'opal'
60
60
  options = option_parser.options
data/bin/opal-mspec ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ specs = ARGV.map do |s|
4
+ s.end_with?('.rb') ? s : "#{s}/**/*_spec.rb"
5
+ end
6
+ pattern = %Q{MSPEC_PATTERN="{#{specs.join(',')}}"} if specs.any?
7
+ command = [pattern, 'rake mspec'].compact.join(' ')
8
+ exec command
9
+
10
+ # bundle exec mspec run -t opal -pspec/corelib/spec_helper spec/corelib/core/true/*
data/bin/opal-repl CHANGED
@@ -19,7 +19,7 @@ module Opal
19
19
 
20
20
  @v8 = V8::Context.new
21
21
  @v8['console'] = self
22
- @v8.eval @builder.build 'opal'
22
+ @v8.eval Opal::Builder.new.build('opal').to_s
23
23
 
24
24
  if filename
25
25
  if File.exist? filename
@@ -56,8 +56,9 @@ module Opal
56
56
  end
57
57
 
58
58
  def eval_ruby(str)
59
- code = @builder.build_str str, :irb => true, :const_missing => true
60
- @v8.eval "var $_result = #{code} ($_result == null ? 'nil' : $_result.$inspect());"
59
+ code = Opal::Builder.new.build_str(str, '(irb)', :irb => true, :const_missing => true)
60
+ code.processed[0...-1].each{ |c| @v8.eval(c.to_s) }
61
+ @v8.eval "var $_result = #{code.processed.last.to_s} ($_result == null ? 'nil' : $_result.$inspect());"
61
62
  rescue => e
62
63
  puts "#{e.message}\n\t#{e.backtrace.join("\n\t")}"
63
64
  end
@@ -1,4 +1,4 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- gem 'opal', :path => '../../opal'
3
+ gem 'opal', :path => '../..'
4
4
  gem 'sinatra'
@@ -6,7 +6,7 @@ opal = Opal::Server.new {|s|
6
6
  s.main = 'application'
7
7
  }
8
8
 
9
- map '/__opal_source_maps__' do
9
+ map opal.source_maps.prefix do
10
10
  run opal.source_maps
11
11
  end
12
12
 
@@ -15,14 +15,14 @@ map '/assets' do
15
15
  end
16
16
 
17
17
  get '/' do
18
- <<-EOS
18
+ <<-HTML
19
19
  <!doctype html>
20
20
  <html>
21
21
  <head>
22
22
  <script src="/assets/application.js"></script>
23
23
  </head>
24
24
  </html>
25
- EOS
25
+ HTML
26
26
  end
27
27
 
28
28
  run Sinatra::Application
@@ -1,8 +1,8 @@
1
- <% require_asset 'spec_helper' %>
1
+ require 'spec_helper'
2
2
 
3
3
  # This file just greps for all spec files in spec/ and requires them
4
4
  <% ENV['OPAL_SPEC'].split(',').each do |s| %>
5
- <% require_asset s %>
5
+ require <%= s.inspect %>
6
6
  <% end %>
7
7
 
8
8
  # All specs have been run, so we notify mspec that we are done
@@ -11,10 +11,14 @@ class Opal::Nodes::CallNode
11
11
  compiler.requires << target
12
12
  end
13
13
 
14
- return fragment("nil")
14
+ push fragment("nil")
15
15
  end
16
+ end
16
17
 
17
- nil
18
+ add_special :not_supported_on do
19
+ unless meth == :not_supported_on and arglist[1][1] == :opal
20
+ compile_default!
21
+ end
18
22
  end
19
23
  end
20
24
 
@@ -24,7 +28,6 @@ require 'webrick'
24
28
 
25
29
  module MSpec
26
30
  module Opal
27
- DEFAULT_PATTERN = 'spec/{corelib,opal,stdlib}/**/*_spec.rb'
28
31
  DEFAULT_BASEDIR = 'spec'
29
32
 
30
33
  require 'rake'
@@ -119,18 +122,21 @@ module MSpec
119
122
 
120
123
  def initialize(basedir = nil, pattern = nil)
121
124
  ::Opal::Processor.arity_check_enabled = true
122
- ::Opal::Processor.dynamic_require_severity = :ignore
123
- super()
125
+ ::Opal::Processor.dynamic_require_severity = :error
126
+
124
127
  @pattern = pattern
125
128
  @basedir = basedir = File.expand_path(basedir || DEFAULT_BASEDIR)
126
- append_path basedir
127
- use_gem 'mspec'
129
+
130
+ ::Opal.append_path basedir
131
+ ::Opal.use_gem 'mspec'
128
132
 
129
133
  stubs.each do |asset|
130
134
  ::Opal::Processor.stub_file asset
131
135
  end
132
136
 
133
137
  ENV['OPAL_SPEC'] ||= files_to_run(pattern).join(',')
138
+
139
+ super()
134
140
  end
135
141
 
136
142
  def stubs
@@ -159,25 +165,23 @@ module MSpec
159
165
  @files ||= []
160
166
  end
161
167
 
162
- def add_files specs
163
- puts "Adding #{specs.size} spec files..."
164
- files.concat specs.flatten
165
- end
166
-
167
- def paths_from_glob pattern
168
- Dir.glob(File.expand_path(pattern)).map do |s|
169
- s.sub(/^#{basedir}\//, '').sub(/\.rb$/, '')
170
- end
171
- end
172
-
173
- def rubyspec_paths
174
- rubyspec_white_list.map do |path|
168
+ def add_files specs, tag = ''
169
+ tag = "[#{tag}] "
170
+ puts "#{tag}Adding #{specs.size} spec files..."
171
+ specs = specs.flatten.map do |path|
175
172
  dirname = File.join([basedir, path])
176
173
  if File.directory? dirname
177
174
  rubyspec_paths_in_dir(dirname, path)
178
175
  else
179
176
  path
180
177
  end
178
+ end.flatten
179
+ files.concat specs
180
+ end
181
+
182
+ def paths_from_glob pattern
183
+ Dir.glob(File.expand_path(pattern)).map do |s|
184
+ s.sub(/^#{basedir}\//, '').sub(/\.rb$/, '')
181
185
  end
182
186
  end
183
187
 
@@ -197,18 +201,20 @@ module MSpec
197
201
 
198
202
  def files_to_run(pattern=nil)
199
203
  # add any filters in spec/filters of specs we dont want to run
200
- add_files paths_from_glob("#{basedir}/filters/**/*.rb")
204
+ add_files paths_from_glob("#{basedir}/filters/**/*.rb"), :filters
201
205
 
202
206
  if pattern
203
207
  # add custom opal specs from spec/
204
- add_files paths_from_glob(pattern) & rubyspec_paths
208
+ add_files paths_from_glob(pattern) & rubyspec_white_list, :rubyspec_custom_pattern
209
+ add_files paths_from_glob(pattern).grep(/(?!spec\/(corelib|stdlib)\/)/), :other_custom_pattern
205
210
 
206
211
  else
207
212
  # add opal specific specs
208
- add_files paths_from_glob("#{basedir}/{opal}/**/*_spec.rb")
213
+ add_files paths_from_glob("#{basedir}/opal/**/*_spec.rb"), 'opal/*'
214
+ add_files paths_from_glob("#{basedir}/lib/{lexer_spec.rb,parser/**/*_spec.rb}"), 'lib/{lexer,parser}'
209
215
 
210
216
  # add any rubyspecs we want to run (defined in spec/rubyspecs)
211
- add_files rubyspec_paths
217
+ add_files rubyspec_white_list, :rubyspec_white_list
212
218
  end
213
219
  end
214
220
 
@@ -246,6 +252,7 @@ module MSpec
246
252
  <!DOCTYPE html>
247
253
  <html>
248
254
  <head>
255
+ <meta charset="UTF-8" />
249
256
  <title>Opal Specs</title>
250
257
  </head>
251
258
  <body>
@@ -133,6 +133,22 @@ class PhantomFormatter < BrowserFormatter
133
133
  def log(str)
134
134
  `console.log(str)`
135
135
  end
136
+
137
+ def after(state)
138
+ super
139
+ unless exception?
140
+ print '.'
141
+ else
142
+ print failure? ? 'F' : 'E'
143
+ end
144
+ end
145
+ end
146
+
147
+ class PhantomDebugFormatter < PhantomFormatter
148
+ def after(state = nil)
149
+ (@exception && state) ? red(state.description) : green(state.description)
150
+ super
151
+ end
136
152
  end
137
153
 
138
154
  module MSpec
@@ -178,7 +194,8 @@ module OutputSilencer
178
194
  original_stdout = $stdout
179
195
  new_stdout = IO.new
180
196
  new_stdout.extend IO::Writable
181
- def new_stdout.write(string) end
197
+ new_stdout.write_proc = ->s{}
198
+
182
199
  begin
183
200
  $stdout = new_stdout
184
201
  yield
@@ -14,6 +14,23 @@ page.onInitialized = function() {
14
14
  });
15
15
  };
16
16
 
17
+ var system = require('system');
18
+ page.onCallback = function(data) {
19
+ switch (data[0]) {
20
+ case 'exit':
21
+ var status = data[1] || 0;
22
+ phantom.exit(status);
23
+ case 'stdout':
24
+ system.stdout.write(data[1] || '');
25
+ break;
26
+ case 'stderr':
27
+ system.stderr.write(data[1] || '');
28
+ break;
29
+ default:
30
+ console.error('Unknown callback data: ', data);
31
+ }
32
+ };
33
+
17
34
  page.open(args[0], function(status) {
18
35
  if (status !== 'success') {
19
36
  console.error("Cannot load: " + args[0]);
data/lib/opal.rb CHANGED
@@ -2,43 +2,10 @@ require 'opal/compiler'
2
2
  require 'opal/builder'
3
3
  require 'opal/erb'
4
4
  require 'opal/sprockets'
5
+ require 'opal/paths'
5
6
  require 'opal/version'
6
7
 
7
8
  # Opal is a ruby to javascript compiler, with a runtime for running
8
9
  # in any javascript environment.
9
10
  module Opal
10
- def self.gem_dir
11
- File.expand_path('..', __FILE__.untaint)
12
- end
13
-
14
- def self.core_dir
15
- File.expand_path('../../opal', __FILE__.untaint)
16
- end
17
-
18
- def self.std_dir
19
- File.expand_path('../../stdlib', __FILE__.untaint)
20
- end
21
-
22
- # Add a file path to opals load path. Any gem containing ruby code that Opal
23
- # has access to should add a load path through this method. Load paths added
24
- # here should only be paths which contain code targeted at being compiled by
25
- # Opal.
26
- def self.append_path(path)
27
- paths << path
28
- end
29
-
30
- def self.use_gem(gem_name, include_dependecies = true)
31
- spec = Gem::Specification.find_by_name(gem_name)
32
-
33
- spec.runtime_dependencies.each do |dependency|
34
- use_gem dependency.name
35
- end if include_dependecies
36
-
37
- Opal.append_path File.join(spec.gem_dir, 'lib')
38
- end
39
-
40
- # Private, don't add to these directly (use .append_path instead).
41
- def self.paths
42
- @paths ||= [core_dir.untaint, std_dir.untaint, gem_dir.untaint]
43
- end
44
11
  end
data/lib/opal/builder.rb CHANGED
@@ -1,101 +1,135 @@
1
- require 'opal/compiler'
2
- require 'erb'
3
- require 'pathname'
1
+ require 'opal/path_reader'
2
+ require 'opal/builder_processors'
3
+ require 'set'
4
4
 
5
5
  module Opal
6
6
  class Builder
7
+ include BuilderProcessors
7
8
 
8
- BUILDERS = { ".rb" => :build_ruby, ".js" => :build_js, ".erb" => :build_erb }
9
+ def initialize(options = nil)
10
+ (options || {}).each_pair do |k,v|
11
+ public_send("#{k}=", v)
12
+ end
13
+
14
+ @compiler_options ||= {}
15
+ @default_processor ||= RubyProcessor
16
+ @processors ||= DEFAULT_PROCESSORS
17
+ @stubs ||= []
18
+ @preload ||= []
19
+ @prerequired ||= []
20
+ @path_reader ||= PathReader.new
9
21
 
10
- def self.build(name)
11
- Builder.new.build name
22
+ @processed = []
12
23
  end
13
24
 
14
- def initialize(options = {})
15
- @paths = options.delete(:paths) || Opal.paths.clone
16
- @options = options
17
- @handled = {}
25
+ def self.build(*args, &block)
26
+ new.build(*args, &block)
18
27
  end
19
28
 
20
- def append_path(path)
21
- @paths << path
29
+ def build(path, options = {})
30
+ source = read(path)
31
+ build_str(source, path, options)
22
32
  end
23
33
 
24
- def build(path)
25
- @segments = []
34
+ def build_str source, filename, options = {}
35
+ path = path_reader.expand(filename).to_s unless stub?(filename)
36
+ asset = processor_for(source, filename, path, options)
37
+ requires = preload + asset.requires + tree_requires(asset, path)
38
+ requires.map { |r| process_require(r, options) }
39
+ processed << asset
40
+ self
41
+ end
26
42
 
27
- require_asset path
43
+ def build_require(path, options = {})
44
+ process_require(path, options)
45
+ end
28
46
 
29
- @segments.join
47
+ def to_s
48
+ processed.map(&:to_s).join("\n")
30
49
  end
31
50
 
32
- def build_str(str, options = {})
33
- @segments = []
34
- @segments << compile_ruby(str, options)
35
- @segments.join
51
+ def source_map
52
+ processed.map(&:source_map).reduce(:+).as_json.to_json
36
53
  end
37
54
 
38
- def require_asset(path)
39
- location = find_asset path
55
+ attr_reader :processed
40
56
 
41
- unless @handled[location]
42
- @handled[location] = true
43
- build_asset location
44
- end
45
- end
57
+ attr_accessor :processors, :default_processor, :path_reader,
58
+ :compiler_options, :stubs, :prerequired, :preload
46
59
 
47
- def find_asset(path)
48
- return path if Pathname(path).absolute?
49
60
 
50
- path.untaint if path =~ /\A(\w[-.\w]*\/?)+\Z/
51
- file_types = %w[.rb .js .js.erb]
52
61
 
53
- @paths.each do |root|
54
- file_types.each do |type|
55
- test = File.join root, "#{path}#{type}"
56
62
 
57
- if File.exist? test
58
- return test
59
- end
60
- end
63
+ private
64
+
65
+ def tree_requires(asset, path)
66
+ if path.nil? or path.empty?
67
+ dirname = Dir.pwd
68
+ else
69
+ dirname = File.dirname(File.expand_path(path))
61
70
  end
62
71
 
63
- raise "Could not find asset: #{path}"
64
- end
72
+ paths = path_reader.paths.map{|p| File.expand_path(p)}
65
73
 
66
- def build_asset(path)
67
- ext = File.extname path
74
+ asset.required_trees.flat_map do |tree|
75
+ expanded = File.expand_path(tree, dirname)
76
+ base = paths.find { |p| expanded.start_with?(p) }
77
+ next [] if base.nil?
68
78
 
69
- unless builder = BUILDERS[ext]
70
- raise "Unknown builder for #{ext}"
79
+ globs = extensions.map { |ext| File.join base, tree, "*.#{ext}" }
80
+
81
+ Dir[*globs].map do |file|
82
+ Pathname(file).relative_path_from(Pathname(base)).to_s.gsub(/(\.js)?(\.(?:#{extensions.join '|'}))$/, '')
83
+ end
71
84
  end
85
+ end
86
+
87
+ def processor_for(source, filename, path, options)
88
+ processor = processors.find { |p| p.match? path }
89
+ processor ||= default_processor
90
+ return processor.new(source, filename, compiler_options.merge(options))
91
+ end
72
92
 
73
- @segments << __send__(builder, path)
93
+ def read(path)
94
+ path_reader.read(path) or
95
+ raise ArgumentError, "can't find file: #{path.inspect} in #{path_reader.paths.inspect}"
74
96
  end
75
97
 
76
- def compile_ruby(str, options = nil)
77
- options ||= @options.clone
98
+ def process_require(filename, options)
99
+ return if prerequired.include?(filename)
100
+ return if already_processed.include?(filename)
101
+ already_processed << filename
78
102
 
79
- compiler = Compiler.new
80
- result = compiler.compile str, options
103
+ source = stub?(filename) ? '' : read(filename)
81
104
 
82
- compiler.requires.each do |r|
83
- require_asset r
105
+ if source.nil?
106
+ message = "can't find file: #{filename.inspect}"
107
+ case @compiler_options[:dynamic_require_severity]
108
+ when :error then raise LoadError, message
109
+ when :warning then warn "can't find file: #{filename.inspect}"
110
+ end
84
111
  end
85
112
 
86
- result
113
+ path = path_reader.expand(filename).to_s unless stub?(filename)
114
+ asset = processor_for(source, filename, path, options.merge(requirable: true))
115
+ process_requires(asset.requires+tree_requires(asset, path), options)
116
+ processed << asset
117
+ end
118
+
119
+ def process_requires(requires, options)
120
+ requires.map { |r| process_require(r, options) }
87
121
  end
88
122
 
89
- def build_ruby(path)
90
- compile_ruby File.read(path), @options.clone
123
+ def already_processed
124
+ @already_processed ||= Set.new
91
125
  end
92
126
 
93
- def build_js(path)
94
- File.read(path)
127
+ def stub? filename
128
+ stubs.include?(filename)
95
129
  end
96
130
 
97
- def build_erb(path)
98
- ::ERB.new(File.read(path)).result binding
131
+ def extensions
132
+ @extensions ||= DEFAULT_PROCESSORS.flat_map(&:extensions).compact
99
133
  end
100
134
  end
101
135
  end