opal 0.6.3 → 0.7.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -3,101 +3,147 @@ require 'optparse'
3
3
  module Opal
4
4
  class CLIOptions < OptionParser
5
5
  def initialize
6
+ super
6
7
  @options = {}
7
8
 
8
- super do |opts|
9
- opts.banner = 'Usage: opal [options] -- [programfile]'
10
-
11
- opts.on('-v', '--verbose', 'print version number, then turn on verbose mode') do |v|
12
- require 'opal/version'
13
- puts "Opal v#{Opal::VERSION}"
14
- options[:verbose] = true # TODO: print some warnings when verbose = true
15
- end
16
-
17
- opts.on('--version', 'Print the version') do |v|
18
- require 'opal/version'
19
- puts "Opal v#{Opal::VERSION}"
20
- exit
21
- end
22
-
23
- opts.on("-h", "--help", "Show this message") do
24
- puts opts
25
- exit
26
- end
27
-
28
- opts.separator ''
29
- opts.separator 'Basic Options:'
30
-
31
- opts.on('-I', '--include DIR',
32
- 'Append a load path (may be used more than once)') do |i|
33
- options[:load_paths] ||= []
34
- options[:load_paths] << i
35
- end
36
-
37
- opts.on('-e', '--eval SOURCE', String,
38
- 'One line of script. Several -e\'s allowed. Omit [programfile]') do |source|
39
- options[:evals] ||= []
40
- options[:evals] << source
41
- end
42
-
43
- opts.on('-r', '--require LIBRARY', String,
44
- 'Require the library before executing your script') do |library|
45
- options[:requires] ||= []
46
- options[:requires] << library
47
- end
48
-
49
- opts.on('-s', '--sexp', 'Show Sexps') do
50
- options[:sexp] = true
51
- end
52
-
53
- opts.on('-m', '--map', 'Show sourcemap') do
54
- options[:map] = true
55
- end
56
-
57
- opts.on('-c', '--compile', 'Compile to JavaScript') do
58
- options[:compile] = true
59
- end
60
-
61
- opts.on('-s', '--server [PORT]', 'Start a server (default port: 3000)') do |port|
62
- options[:server] = port.to_i
63
- end
64
-
65
-
66
- opts.separator ''
67
- opts.separator 'Compilation Options:'
68
-
69
- opts.on('-M', '--[no-]method-missing', 'Disable method missing') do |val|
70
- options[:method_missing] = val
71
- end
72
-
73
- opts.on('-A', '--[no-]arity-check', 'Enable arity check') do |value|
74
- options[:arity_check] = value
75
- end
76
-
77
- opts.on('-C', '--[no-]const-missing', 'Disable const missing') do |value|
78
- options[:const_missing] = value
79
- end
80
-
81
- dynamic_require_levels = %w[error warning ignore]
82
- opts.on('-D', '--dynamic-require LEVEL', dynamic_require_levels,
83
- 'Set levelDynamic require severity') do |level|
84
- options[:dynamic_require_severity] = level.to_sym
85
- end
86
-
87
- opts.on('-P', '--no-source-map', 'Disable source map') do |value|
88
- options[:source_map_enabled] = false
89
- end
90
-
91
- opts.on('-F', '--file FILE', 'Set filename for compiled code') do |file|
92
- options[:file] = file
93
- end
94
-
95
- opts.on("--[no-]irb", "IRB var mode") do |flag|
96
- options[:irb] = flag
97
- end
9
+ self.banner = 'Usage: opal [options] -- [programfile]'
10
+
11
+ separator ''
12
+
13
+ on('-v', '--verbose', 'print version number, then turn on verbose mode') do
14
+ print_version
15
+ options[:verbose] = true # TODO: print some warnings when verbose = true
16
+ end
17
+
18
+ on('--verbose', 'turn on verbose mode') do
19
+ options[:verbose] = true # TODO: print some warnings when verbose = true
20
+ end
21
+
22
+ on('--version', 'Print the version') do
23
+ print_version
24
+ exit
25
+ end
26
+
27
+ on("-h", "--help", "Show this message") do
28
+ puts self
29
+ exit
30
+ end
31
+
32
+
33
+ section 'Basic Options:'
34
+
35
+ on('-I', '--include DIR',
36
+ 'Append a load path (may be used more than once)') do |i|
37
+ options[:load_paths] ||= []
38
+ options[:load_paths] << i
39
+ end
40
+
41
+ on('-e', '--eval SOURCE', String,
42
+ 'One line of script. Several -e\'s allowed. Omit [programfile]') do |source|
43
+ options[:evals] ||= []
44
+ options[:evals] << source
45
+ end
46
+
47
+ on('-r', '--require LIBRARY', String,
48
+ 'Require the library before executing your script') do |library|
49
+ options[:requires] ||= []
50
+ options[:requires] << library
51
+ end
52
+
53
+ on('-s', '--stub FILE', String, 'Stubbed files will be compiled as empty files') do |stub|
54
+ options[:stubs] ||= []
55
+ options[:stubs] << stub
56
+ end
57
+
58
+ on('-p', '--preload FILE', String, 'Preloaded files will be prepared for dynamic requires') do |stub|
59
+ options[:preload] ||= []
60
+ options[:preload] << stub
61
+ end
62
+
63
+ on('-g', '--gem GEM_NAME', String, 'Adds the specified GEM_NAME to Opal\'s load path.') do |g|
64
+ options[:gems] ||= []
65
+ options[:gems] << g
66
+ end
67
+
68
+ section 'Running Options:'
69
+
70
+ on('--sexp', 'Show Sexps') do
71
+ options[:sexp] = true
72
+ end
73
+
74
+ on('-m', '--map', 'Show sourcemap') do
75
+ options[:map] = true
76
+ end
77
+
78
+ on('-c', '--compile', 'Compile to JavaScript') do
79
+ options[:compile] = true
98
80
  end
81
+
82
+ on('--runner RUNNER', %w[nodejs server phantomjs], 'Choose the runner: nodejs (default), server') do |runner|
83
+ options[:runner] = runner.to_sym
84
+ end
85
+
86
+ on('--server-port PORT', 'Set the port for the server runner (default port: 3000)') do |port|
87
+ options[:runner] = :server
88
+ options[:port] = port.to_i
89
+ end
90
+
91
+
92
+ section 'Compilation Options:'
93
+
94
+ on('-M', '--no-method-missing', 'Enable/Disable method missing') do
95
+ options[:method_missing] = false
96
+ end
97
+
98
+ on('-O', '--no-opal', 'Enable/Disable implicit `require "opal"`') do
99
+ options[:skip_opal_require] = true
100
+ end
101
+
102
+ on('-A', '--arity-check', 'Enable arity check') do
103
+ options[:arity_check] = true
104
+ end
105
+
106
+ on('-V', 'Enable inline Operators') do
107
+ options[:inline_operators] = true
108
+ end
109
+
110
+ dynamic_require_levels = %w[error warning ignore]
111
+ on('-D', '--dynamic-require LEVEL', dynamic_require_levels,
112
+ 'Set level of dynamic require severity.',
113
+ "(deafult: error, values: #{dynamic_require_levels.join(', ')})") do |level|
114
+ options[:dynamic_require_severity] = level.to_sym
115
+ end
116
+
117
+ on('-P', '--source-map [FILE]', 'Enable/Disable source map') do |file|
118
+ options[:source_map_enabled] = true
119
+ options[:source_map_file] = file if file
120
+ end
121
+
122
+ on('-F', '--file FILE', 'Set filename for compiled code') do |file|
123
+ options[:file] = file
124
+ end
125
+
126
+ on("--irb", "Enable IRB var mode") do
127
+ options[:irb] = true
128
+ end
129
+
130
+ separator ''
99
131
  end
100
132
 
101
133
  attr_reader :options
134
+
135
+
136
+ private
137
+
138
+ def print_version
139
+ require 'opal/version'
140
+ puts "Opal v#{Opal::VERSION}"
141
+ end
142
+
143
+ def section title
144
+ separator ''
145
+ separator title
146
+ separator ''
147
+ end
102
148
  end
103
149
  end
@@ -0,0 +1,10 @@
1
+ module Opal
2
+ module CliRunners
3
+ class RunnerError < StandardError
4
+ end
5
+ end
6
+ end
7
+
8
+ require 'opal/cli_runners/phantomjs'
9
+ require 'opal/cli_runners/nodejs'
10
+ require 'opal/cli_runners/server'
@@ -0,0 +1,56 @@
1
+ require 'opal/cli_runners'
2
+
3
+ module Opal
4
+ module CliRunners
5
+ class Nodejs
6
+ def initialize(output)
7
+ @output ||= output
8
+ end
9
+ attr_reader :output
10
+
11
+ def puts(*args)
12
+ output.puts(*args)
13
+ end
14
+
15
+ def node_modules
16
+ File.expand_path("../../../../node_modules", __FILE__)
17
+ end
18
+
19
+ def run(code, argv)
20
+ require 'tempfile'
21
+ tempfile = Tempfile.new('opal-nodejs-runner-')
22
+ # tempfile = File.new('opal-nodejs-runner.js', 'w') # for debugging
23
+ tempfile.write code
24
+ tempfile.close
25
+ system_with_output({'NODE_PATH' => node_modules}, 'node', tempfile.path , *argv)
26
+ rescue Errno::ENOENT
27
+ raise MissingNodeJS, 'Please install Node.js to be able to run Opal scripts.'
28
+ end
29
+
30
+ # Let's support fake IO objects like StringIO
31
+ def system_with_output(env, *cmd)
32
+ io_output = IO.try_convert(output)
33
+ return system(env,*cmd) if io_output
34
+
35
+ if RUBY_PLATFORM == 'java'
36
+ # JRuby has issues in dealing with subprocesses (at least up to 1.7.15)
37
+ # @headius told me it's mostly fixed on master, but while we wait for it
38
+ # to ship here's a tempfile workaround.
39
+ require 'tempfile'
40
+ require 'shellwords'
41
+ tempfile = Tempfile.new('opal-node-output')
42
+ system(env,cmd.shelljoin+" > #{tempfile.path}")
43
+ captured_output = File.read tempfile.path
44
+ tempfile.close
45
+ else
46
+ require 'open3'
47
+ captured_output, status = Open3.capture2(env,*cmd)
48
+ end
49
+ output.write captured_output
50
+ end
51
+
52
+ class MissingNodeJS < RunnerError
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,35 @@
1
+ var page = require('webpage').create();
2
+ var fs = require('fs');
3
+ var system = require('system');
4
+
5
+ page.onConsoleMessage = function(msg) {
6
+ system.stdout.write(msg);
7
+ };
8
+
9
+ var opal_code = fs.read('/dev/stdin');
10
+
11
+ page.onCallback = function(data) {
12
+ switch (data[0]) {
13
+ case 'exit':
14
+ var status = data[1] || 0;
15
+ phantom.exit(status);
16
+ case 'stdout':
17
+ system.stdout.write(data[1] || '');
18
+ break;
19
+ case 'stderr':
20
+ system.stderr.write(data[1] || '');
21
+ break;
22
+ default:
23
+ console.error('Unknown callback data: ', data);
24
+ }
25
+ };
26
+
27
+ page.content = '<!doctype html>'+
28
+ '<html>'+
29
+ ' <head><meta charset="utf-8"/></head>'+
30
+ " <body><script>//<![CDATA[\n"+
31
+ opal_code+
32
+ " //]]></script>"+
33
+ ' <script>callPhantom(["exit", 0]);</script></body>\n'+
34
+ ' </body>'+
35
+ '</html>';
@@ -0,0 +1,28 @@
1
+ require 'shellwords'
2
+
3
+ module Opal
4
+ module CliRunners
5
+ class Phantomjs
6
+ def initialize(output = $stdout)
7
+ @output = output
8
+ end
9
+ attr_reader :output
10
+
11
+ def run(code, argv)
12
+ unless argv.empty?
13
+ raise ArgumentError, 'Program arguments are not supported on the PhantomJS runner'
14
+ end
15
+
16
+ phantomjs = IO.popen(command, 'w', out: output) do |io|
17
+ io.write(code)
18
+ end
19
+ exit $?.exitstatus
20
+ end
21
+
22
+ def command
23
+ script_path = File.expand_path('../phantom.js', __FILE__)
24
+ "phantomjs #{script_path.shellescape}"
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,54 @@
1
+ require 'opal/cli_runners'
2
+
3
+ module Opal
4
+ module CliRunners
5
+ class Server
6
+ def initialize(output, port)
7
+ @output ||= output || $stdout
8
+ @port = port
9
+ end
10
+ attr_reader :output, :port, :server
11
+
12
+ def run(source, argv)
13
+ unless argv.empty?
14
+ raise ArgumentError, 'Program arguments are not supported on the PhantomJS runner'
15
+ end
16
+
17
+ require 'rack'
18
+ require 'webrick'
19
+ require 'logger'
20
+
21
+ @server = Rack::Server.start(
22
+ :app => app(source),
23
+ :Port => port,
24
+ :AccessLog => [],
25
+ :Logger => Logger.new(output)
26
+ )
27
+ end
28
+
29
+ def app(source)
30
+ lambda do |env|
31
+ case env['PATH_INFO']
32
+ when '/'
33
+ body = <<-HTML
34
+ <!doctype html>
35
+ <html>
36
+ <head>
37
+ <meta charset="utf-8"/>
38
+ <script>
39
+ //<![CDATA[
40
+ #{source}
41
+ //]]>
42
+ </script>
43
+ </head>
44
+ </html>
45
+ HTML
46
+ [200, {}, [body]]
47
+ else
48
+ [404, {}, [body]]
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
data/lib/opal/compiler.rb CHANGED
@@ -5,7 +5,7 @@ require 'opal/nodes'
5
5
 
6
6
  module Opal
7
7
  def self.compile(source, options = {})
8
- Compiler.new.compile(source, options)
8
+ Compiler.new(source, options).compile
9
9
  end
10
10
 
11
11
  class Compiler
@@ -17,9 +17,13 @@ module Opal
17
17
  COMPARE = %w[< > <= >=]
18
18
 
19
19
  # defines a compiler option, also creating method of form 'name?'
20
- def self.compiler_option(name, default_value, mid = nil)
20
+ def self.compiler_option(name, default_value, options = {})
21
+ mid = options[:as]
22
+ valid_values = options[:valid_values]
21
23
  define_method(mid || name) do
22
- @options.fetch(name) { default_value }
24
+ value = @options.fetch(name) { default_value }
25
+ raise ArgumentError if valid_values and not(valid_values.include?(value))
26
+ value
23
27
  end
24
28
  end
25
29
 
@@ -27,19 +31,22 @@ module Opal
27
31
  compiler_option :file, '(file)'
28
32
 
29
33
  # adds method stubs for all used methods in file
30
- compiler_option :method_missing, true, :method_missing?
34
+ compiler_option :method_missing, true, :as => :method_missing?
31
35
 
32
36
  # adds an arity check to every method definition
33
- compiler_option :arity_check, false, :arity_check?
34
-
35
- # checks every constant access, delagating to const_missing if needed
36
- compiler_option :const_missing, false, :const_missing?
37
+ compiler_option :arity_check, false, :as => :arity_check?
37
38
 
38
39
  # compile top level local vars with support for irb style vars
39
- compiler_option :irb, false, :irb?
40
+ compiler_option :irb, false, :as => :irb?
40
41
 
41
42
  # how to handle dynamic requires (:error, :warning, :ignore)
42
- compiler_option :dynamic_require_severity, :error
43
+ compiler_option :dynamic_require_severity, :error, :valid_values => [:error, :warning, :ignore]
44
+
45
+ # Prepare the code for future requires
46
+ compiler_option :requirable, false, :as => :requirable?
47
+
48
+ # are operators compiled inline
49
+ compiler_option :inline_operators, false, :as => :inline_operators?
43
50
 
44
51
  attr_reader :result, :fragments
45
52
 
@@ -52,16 +59,15 @@ module Opal
52
59
  # Any content in __END__ special construct
53
60
  attr_reader :eof_content
54
61
 
55
- def initialize
62
+ def initialize(source, options = {})
63
+ @source = source
56
64
  @indent = ''
57
65
  @unique = 0
58
- @options = {}
66
+ @options = options
59
67
  end
60
68
 
61
69
  # Compile some ruby code to a string.
62
- def compile(source, options = {})
63
- @source = source
64
- @options.update options
70
+ def compile
65
71
  @parser = Parser.new
66
72
 
67
73
  @sexp = s(:top, @parser.parse(@source, self.file) || s(:nil))
@@ -81,6 +87,11 @@ module Opal
81
87
  @helpers ||= Set.new([:breaker, :slice])
82
88
  end
83
89
 
90
+ # Operator helpers
91
+ def operator_helpers
92
+ @operator_helpers ||= Set.new
93
+ end
94
+
84
95
  # Method calls made in this file
85
96
  def method_calls
86
97
  @method_calls ||= Set.new
@@ -97,7 +108,7 @@ module Opal
97
108
  # method simply appends the filename and curent line number onto
98
109
  # the message and issues a warning.
99
110
  def warning(msg, line = nil)
100
- warn "#{msg} :#{file}:#{line}"
111
+ warn "WARNING: #{msg} :#{file}:#{line}"
101
112
  end
102
113
 
103
114
  # Instances of `Scope` can use this to determine the current
@@ -182,6 +193,8 @@ module Opal
182
193
  # Process the given sexp by creating a node instance, based on its type,
183
194
  # and compiling it to fragments.
184
195
  def process(sexp, level = :expr)
196
+ return fragment('') if sexp == nil
197
+
185
198
  if handler = handlers[sexp.type]
186
199
  return handler.new(sexp, level, self).compile_to_fragments
187
200
  else
@@ -198,6 +211,12 @@ module Opal
198
211
  @requires ||= []
199
212
  end
200
213
 
214
+ # An array of trees required in this file
215
+ # (typically by calling #require_tree)
216
+ def required_trees
217
+ @required_trees ||= []
218
+ end
219
+
201
220
  # The last sexps in method bodies, for example, need to be returned
202
221
  # in the compiled javascript. Due to syntax differences between
203
222
  # javascript any ruby, some sexps need to be handled specially. For