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
@@ -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