opal 0.3.21 → 0.3.22

Sign up to get free protection for your applications and to get access to all the features.
Files changed (297) hide show
  1. data/.travis.yml +1 -4
  2. data/Gemfile +9 -4
  3. data/README.md +10 -589
  4. data/Rakefile +51 -19
  5. data/config.ru +17 -0
  6. data/core/array.rb +42 -34
  7. data/core/basic_object.rb +4 -4
  8. data/core/browser.js +31 -0
  9. data/core/class.rb +7 -7
  10. data/core/enumerable.rb +65 -69
  11. data/core/erb.rb +30 -0
  12. data/core/error.rb +2 -3
  13. data/core/hash.rb +47 -18
  14. data/core/kernel.rb +15 -16
  15. data/core/load_order +2 -1
  16. data/core/module.rb +19 -37
  17. data/core/numeric.rb +4 -2
  18. data/core/object.rb +4 -0
  19. data/core/proc.rb +6 -3
  20. data/core/racc.rb +215 -0
  21. data/core/regexp.rb +16 -21
  22. data/core/runtime.js +141 -153
  23. data/core/string.rb +41 -19
  24. data/core/strscan.rb +61 -0
  25. data/core/time.rb +1 -5
  26. data/docs/index.md +616 -0
  27. data/docs/post.html +2 -8
  28. data/docs/pre.html +29 -26
  29. data/docs/try.html +52 -0
  30. data/lib/opal.rb +33 -3
  31. data/lib/opal/builder.rb +14 -34
  32. data/lib/opal/erb_parser.rb +19 -0
  33. data/lib/opal/grammar.rb +7 -3
  34. data/lib/opal/grammar.y +3 -0
  35. data/lib/opal/lexer.rb +16 -8
  36. data/lib/opal/parser.rb +156 -119
  37. data/lib/opal/rake_task.rb +2 -2
  38. data/lib/opal/scope.rb +9 -10
  39. data/lib/opal/version.rb +1 -1
  40. data/{test → spec}/core/array/allocate_spec.rb +0 -0
  41. data/{test → spec}/core/array/append_spec.rb +0 -0
  42. data/{test → spec}/core/array/assoc_spec.rb +0 -0
  43. data/{test → spec}/core/array/at_spec.rb +0 -0
  44. data/{test → spec}/core/array/clear_spec.rb +0 -0
  45. data/{test → spec}/core/array/clone_spec.rb +0 -0
  46. data/{test → spec}/core/array/collect_spec.rb +0 -0
  47. data/{test → spec}/core/array/compact_spec.rb +0 -0
  48. data/{test → spec}/core/array/concat_spec.rb +0 -0
  49. data/{test → spec}/core/array/constructor_spec.rb +0 -0
  50. data/{test → spec}/core/array/count_spec.rb +0 -0
  51. data/{test → spec}/core/array/delete_at_spec.rb +0 -0
  52. data/{test → spec}/core/array/delete_if_spec.rb +0 -0
  53. data/{test → spec}/core/array/delete_spec.rb +0 -0
  54. data/{test → spec}/core/array/each_index_spec.rb +0 -0
  55. data/{test → spec}/core/array/each_spec.rb +0 -0
  56. data/{test → spec}/core/array/element_reference_spec.rb +0 -0
  57. data/{test → spec}/core/array/empty_spec.rb +0 -0
  58. data/{test → spec}/core/array/eql_spec.rb +0 -0
  59. data/{test → spec}/core/array/fetch_spec.rb +0 -0
  60. data/{test → spec}/core/array/first_spec.rb +0 -0
  61. data/{test → spec}/core/array/flatten_spec.rb +0 -0
  62. data/{test → spec}/core/array/include_spec.rb +0 -0
  63. data/{test → spec}/core/array/insert_spec.rb +0 -0
  64. data/{test → spec}/core/array/last_spec.rb +0 -0
  65. data/{test → spec}/core/array/length_spec.rb +0 -0
  66. data/{test → spec}/core/array/map_spec.rb +0 -0
  67. data/{test → spec}/core/array/minus_spec.rb +0 -0
  68. data/{test → spec}/core/array/plus_spec.rb +0 -0
  69. data/{test → spec}/core/array/pop_spec.rb +0 -0
  70. data/{test → spec}/core/array/push_spec.rb +0 -0
  71. data/{test → spec}/core/array/rassoc_spec.rb +0 -0
  72. data/{test → spec}/core/array/reject_spec.rb +0 -0
  73. data/{test → spec}/core/array/replace_spec.rb +0 -0
  74. data/{test → spec}/core/array/reverse_each_spec.rb +0 -0
  75. data/{test → spec}/core/array/reverse_spec.rb +0 -0
  76. data/{test → spec}/core/array/size_spec.rb +0 -0
  77. data/{test → spec}/core/array/to_ary_spec.rb +0 -0
  78. data/{test → spec}/core/array/uniq_spec.rb +0 -0
  79. data/{test → spec}/core/array/zip_spec.rb +0 -0
  80. data/{test → spec}/core/class/fixtures/classes.rb +0 -0
  81. data/{test → spec}/core/class/new_spec.rb +3 -0
  82. data/{test → spec}/core/enumerable/all_spec.rb +3 -0
  83. data/{test → spec}/core/enumerable/any_spec.rb +0 -0
  84. data/{test → spec}/core/enumerable/collect_spec.rb +0 -0
  85. data/{test → spec}/core/enumerable/count_spec.rb +0 -0
  86. data/{test → spec}/core/enumerable/detect_spec.rb +0 -0
  87. data/{test → spec}/core/enumerable/drop_spec.rb +0 -0
  88. data/{test → spec}/core/enumerable/drop_while_spec.rb +0 -0
  89. data/{test → spec}/core/enumerable/each_with_index_spec.rb +0 -0
  90. data/{test → spec}/core/enumerable/each_with_object_spec.rb +0 -0
  91. data/{test → spec}/core/enumerable/entries_spec.rb +0 -0
  92. data/{test → spec}/core/enumerable/find_all_spec.rb +0 -0
  93. data/{test → spec}/core/enumerable/find_index_spec.rb +0 -0
  94. data/{test → spec}/core/enumerable/find_spec.rb +0 -0
  95. data/{test → spec}/core/enumerable/first_spec.rb +0 -0
  96. data/{test → spec}/core/enumerable/fixtures/classes.rb +0 -0
  97. data/{test → spec}/core/enumerable/grep_spec.rb +0 -0
  98. data/{test → spec}/core/enumerable/take_spec.rb +0 -0
  99. data/{test → spec}/core/enumerable/to_a_spec.rb +0 -0
  100. data/{test → spec}/core/false/and_spec.rb +0 -0
  101. data/{test → spec}/core/false/inspect_spec.rb +0 -0
  102. data/{test → spec}/core/false/or_spec.rb +0 -0
  103. data/{test → spec}/core/false/to_s_spec.rb +0 -0
  104. data/{test → spec}/core/false/xor_spec.rb +0 -0
  105. data/{test → spec}/core/hash/allocate_spec.rb +0 -0
  106. data/{test → spec}/core/hash/assoc_spec.rb +0 -0
  107. data/{test → spec}/core/hash/clear_spec.rb +0 -0
  108. data/{test → spec}/core/hash/clone_spec.rb +0 -0
  109. data/{test → spec}/core/hash/default_spec.rb +0 -0
  110. data/{test → spec}/core/hash/delete_if_spec.rb +0 -0
  111. data/{test → spec}/core/hash/each_key_spec.rb +0 -0
  112. data/{test → spec}/core/hash/each_pair_spec.rb +0 -0
  113. data/{test → spec}/core/hash/each_spec.rb +0 -0
  114. data/{test → spec}/core/hash/each_value_spec.rb +0 -0
  115. data/{test → spec}/core/hash/element_reference_spec.rb +14 -1
  116. data/{test → spec}/core/hash/element_set_spec.rb +0 -0
  117. data/{test → spec}/core/hash/empty_spec.rb +0 -0
  118. data/{test → spec}/core/hash/fetch_spec.rb +0 -0
  119. data/{test → spec}/core/hash/flatten_spec.rb +0 -0
  120. data/{test → spec}/core/hash/has_key_spec.rb +0 -0
  121. data/{test → spec}/core/hash/has_value_spec.rb +0 -0
  122. data/{test → spec}/core/hash/include_spec.rb +0 -0
  123. data/{test → spec}/core/hash/index_spec.rb +0 -0
  124. data/{test → spec}/core/hash/indexes_spec.rb +0 -0
  125. data/{test → spec}/core/hash/indices_spec.rb +0 -0
  126. data/{test → spec}/core/hash/invert_spec.rb +0 -0
  127. data/{test → spec}/core/hash/keep_if_spec.rb +0 -0
  128. data/{test → spec}/core/hash/key_spec.rb +0 -0
  129. data/{test → spec}/core/hash/keys_spec.rb +0 -0
  130. data/{test → spec}/core/hash/length_spec.rb +0 -0
  131. data/{test → spec}/core/hash/member_spec.rb +0 -0
  132. data/{test → spec}/core/hash/merge_spec.rb +0 -0
  133. data/{test → spec}/core/hash/new_spec.rb +8 -0
  134. data/{test → spec}/core/hash/rassoc_spec.rb +0 -0
  135. data/{test → spec}/core/hash/replace_spec.rb +0 -0
  136. data/{test → spec}/core/hash/select_spec.rb +0 -0
  137. data/{test → spec}/core/hash/shift_spec.rb +0 -0
  138. data/{test → spec}/core/hash/size_spec.rb +0 -0
  139. data/{test → spec}/core/hash/update_spec.rb +0 -0
  140. data/{test → spec}/core/hash/value_spec.rb +0 -0
  141. data/{test → spec}/core/hash/values_at_spec.rb +0 -0
  142. data/{test → spec}/core/hash/values_spec.rb +0 -0
  143. data/{test → spec}/core/kernel/define_singleton_method_spec.rb +0 -0
  144. data/{test → spec}/core/kernel/eql_spec.rb +0 -0
  145. data/{test → spec}/core/kernel/equal_value_spec.rb +0 -0
  146. data/{test → spec}/core/kernel/loop_spec.rb +0 -0
  147. data/{test → spec}/core/kernel/nil_spec.rb +0 -0
  148. data/{test → spec}/core/kernel/proc_spec.rb +4 -0
  149. data/{test → spec}/core/kernel/rand_spec.rb +0 -0
  150. data/{test → spec}/core/kernel/respond_to_spec.rb +0 -0
  151. data/{test → spec}/core/kernel/send_spec.rb +0 -0
  152. data/{test → spec}/core/kernel/tap_spec.rb +0 -0
  153. data/{test → spec}/core/kernel/to_s_spec.rb +0 -0
  154. data/{test → spec}/core/matchdata/to_a_spec.rb +0 -0
  155. data/{test → spec}/core/nil/and_spec.rb +0 -0
  156. data/{test → spec}/core/nil/inspect_spec.rb +0 -0
  157. data/{test → spec}/core/nil/nil_spec.rb +0 -0
  158. data/{test → spec}/core/nil/or_spec.rb +0 -0
  159. data/{test → spec}/core/nil/to_a_spec.rb +0 -0
  160. data/{test → spec}/core/nil/to_f_spec.rb +0 -0
  161. data/{test → spec}/core/nil/to_i_spec.rb +0 -0
  162. data/{test → spec}/core/nil/to_s_spec.rb +0 -0
  163. data/{test → spec}/core/nil/xor_spec.rb +0 -0
  164. data/{test → spec}/core/numeric/equal_value_spec.rb +0 -0
  165. data/spec/core/proc/proc_tricks_spec.rb +7 -0
  166. data/{test → spec}/core/range/begin_spec.rb +0 -0
  167. data/{test → spec}/core/range/case_compare_spec.rb +0 -0
  168. data/{test → spec}/core/range/end_spec.rb +0 -0
  169. data/{test → spec}/core/regexp/match_spec.rb +0 -0
  170. data/{test → spec}/core/string/capitalize_spec.rb +0 -0
  171. data/{test → spec}/core/string/casecmp_spec.rb +0 -0
  172. data/{test → spec}/core/string/chomp_spec.rb +0 -0
  173. data/{test → spec}/core/string/chop_spec.rb +0 -0
  174. data/{test → spec}/core/string/chr_spec.rb +0 -0
  175. data/{test → spec}/core/string/comparison_spec.rb +0 -0
  176. data/{test → spec}/core/string/downcase_spec.rb +0 -0
  177. data/{test → spec}/core/string/element_reference_spec.rb +14 -2
  178. data/{test → spec}/core/string/empty_spec.rb +0 -0
  179. data/{test → spec}/core/string/end_with_spec.rb +0 -0
  180. data/{test → spec}/core/string/fixtures/classes.rb +0 -0
  181. data/{test → spec}/core/string/gsub_spec.rb +0 -0
  182. data/{test → spec}/core/string/include_spec.rb +0 -0
  183. data/{test → spec}/core/string/intern_spec.rb +0 -0
  184. data/{test → spec}/core/string/length_spec.rb +0 -0
  185. data/{test → spec}/core/string/lstrip_spec.rb +0 -0
  186. data/{test → spec}/core/string/match_spec.rb +0 -0
  187. data/{test → spec}/core/string/next_spec.rb +0 -0
  188. data/{test → spec}/core/string/ord_spec.rb +0 -0
  189. data/{test → spec}/core/string/partition_spec.rb +0 -0
  190. data/{test → spec}/core/string/reverse_spec.rb +0 -0
  191. data/{test → spec}/core/string/rstrip_spec.rb +0 -0
  192. data/{test → spec}/core/string/size_spec.rb +0 -0
  193. data/{test → spec}/core/string/slice_spec.rb +4 -1
  194. data/{test → spec}/core/string/split_spec.rb +0 -0
  195. data/{test → spec}/core/string/start_with_spec.rb +0 -0
  196. data/{test → spec}/core/string/strip_spec.rb +0 -0
  197. data/{test → spec}/core/string/sub_spec.rb +0 -0
  198. data/{test → spec}/core/string/succ_spec.rb +0 -0
  199. data/{test → spec}/core/string/sum_spec.rb +0 -0
  200. data/{test → spec}/core/string/swapcase_spec.rb +0 -0
  201. data/{test → spec}/core/string/to_a_spec.rb +0 -0
  202. data/{test → spec}/core/string/to_f_spec.rb +0 -0
  203. data/{test → spec}/core/string/to_i_spec.rb +0 -0
  204. data/{test → spec}/core/string/to_s_spec.rb +0 -0
  205. data/{test → spec}/core/string/to_str_spec.rb +0 -0
  206. data/{test → spec}/core/string/to_sym_spec.rb +0 -0
  207. data/{test → spec}/core/string/upcase_spec.rb +0 -0
  208. data/{test → spec}/core/symbol/to_proc_spec.rb +0 -0
  209. data/{test → spec}/core/time/at_spec.rb +0 -0
  210. data/{test → spec}/core/time/day_spec.rb +0 -0
  211. data/{test → spec}/core/time/friday_spec.rb +0 -0
  212. data/{test → spec}/core/time/hour_spec.rb +0 -0
  213. data/{test → spec}/core/time/min_spec.rb +0 -0
  214. data/{test → spec}/core/time/monday_spec.rb +0 -0
  215. data/{test → spec}/core/time/month_spec.rb +0 -0
  216. data/{test → spec}/core/time/now_spec.rb +0 -0
  217. data/{test → spec}/core/time/saturday_spec.rb +0 -0
  218. data/{test → spec}/core/true/and_spec.rb +0 -0
  219. data/{test → spec}/core/true/inspect_spec.rb +0 -0
  220. data/{test → spec}/core/true/or_spec.rb +0 -0
  221. data/{test → spec}/core/true/to_s_spec.rb +0 -0
  222. data/{test → spec}/core/true/xor_spec.rb +0 -0
  223. data/spec/grammar/lvar_spec.rb +2 -1
  224. data/spec/grammar/str_spec.rb +1 -1
  225. data/spec/grammar/xstr_spec.rb +1 -1
  226. data/{test → spec}/index.html +3 -3
  227. data/{test → spec}/language/alias_spec.rb +0 -0
  228. data/{test → spec}/language/and_spec.rb +0 -0
  229. data/{test → spec}/language/array_spec.rb +0 -0
  230. data/{test → spec}/language/block_spec.rb +0 -0
  231. data/{test → spec}/language/break_spec.rb +0 -0
  232. data/{test → spec}/language/case_spec.rb +0 -0
  233. data/{test → spec}/language/defined_spec.rb +0 -0
  234. data/{test → spec}/language/ensure_spec.rb +2 -2
  235. data/{test → spec}/language/fixtures/next.rb +0 -0
  236. data/{test → spec}/language/fixtures/yield.rb +0 -0
  237. data/{test → spec}/language/hash_spec.rb +0 -0
  238. data/{test → spec}/language/if_spec.rb +0 -0
  239. data/{test → spec}/language/literal_lambda_spec.rb +0 -0
  240. data/{test → spec}/language/loop_spec.rb +0 -0
  241. data/{test → spec}/language/metaclass_spec.rb +0 -0
  242. data/{test → spec}/language/next_spec.rb +2 -0
  243. data/{test → spec}/language/or_spec.rb +0 -0
  244. data/{test → spec}/language/predefined_spec.rb +0 -0
  245. data/{test → spec}/language/regexp_spec.rb +0 -0
  246. data/{test → spec}/language/send_spec.rb +0 -0
  247. data/{test → spec}/language/singleton_class_spec.rb +0 -0
  248. data/{test → spec}/language/super_spec.rb +0 -0
  249. data/{test → spec}/language/symbol_spec.rb +0 -0
  250. data/{test → spec}/language/undef_spec.rb +0 -0
  251. data/{test → spec}/language/unless_spec.rb +0 -0
  252. data/{test → spec}/language/until_spec.rb +0 -0
  253. data/{test → spec}/language/variables_spec.rb +0 -0
  254. data/{test → spec}/language/while_spec.rb +0 -0
  255. data/{test → spec}/language/yield_spec.rb +2 -0
  256. data/{test → spec}/opal/array/subclassing_spec.rb +0 -0
  257. data/{test → spec}/opal/array/to_json_spec.rb +0 -0
  258. data/{test → spec}/opal/boolean/singleton_class_spec.rb +0 -0
  259. data/{test → spec}/opal/boolean/to_json_spec.rb +0 -0
  260. data/{test → spec}/opal/class/bridge_class_spec.rb +0 -0
  261. data/spec/opal/erb/erb_spec.rb +15 -0
  262. data/{test → spec}/opal/exception/subclassing_spec.rb +0 -0
  263. data/{test → spec}/opal/hash/to_json_spec.rb +0 -0
  264. data/spec/opal/hash/to_native_spec.rb +5 -0
  265. data/{test → spec}/opal/json/parse_spec.rb +0 -0
  266. data/{test → spec}/opal/kernel/to_json_spec.rb +0 -0
  267. data/{test → spec}/opal/nil/to_json_spec.rb +0 -0
  268. data/{test → spec}/opal/numeric/to_json_spec.rb +0 -0
  269. data/{test → spec}/opal/runtime/call_spec.rb +0 -0
  270. data/{test → spec}/opal/runtime/class_hierarchy_spec.rb +0 -0
  271. data/{test → spec}/opal/runtime/def_spec.rb +0 -0
  272. data/{test → spec}/opal/runtime/defined_spec.rb +0 -0
  273. data/{test → spec}/opal/runtime/method_missing_spec.rb +3 -3
  274. data/{test → spec}/opal/runtime/super_spec.rb +0 -0
  275. data/{test → spec}/opal/string/subclassing_spec.rb +0 -0
  276. data/{test → spec}/opal/string/to_json_spec.rb +0 -0
  277. data/spec/opal/strscan/check_spec.rb +13 -0
  278. data/spec/opal/strscan/scan_spec.rb +33 -0
  279. data/spec/parser/simple_spec.rb +44 -0
  280. data/spec/spec_helper.rb +7 -7
  281. metadata +487 -497
  282. data/core/dir.rb +0 -89
  283. data/core/file.rb +0 -85
  284. data/spec/browser_spec.rb +0 -28
  285. data/spec/builder/fixtures/build_source/adam.rb +0 -0
  286. data/spec/builder/fixtures/build_source/bar/a.rb +0 -0
  287. data/spec/builder/fixtures/build_source/bar/wow/b.rb +0 -0
  288. data/spec/builder/fixtures/build_source/bar/wow/cow/c.rb +0 -0
  289. data/spec/builder/fixtures/build_source/beynon.rb +0 -0
  290. data/spec/builder/fixtures/build_source/charles.js +0 -0
  291. data/spec/builder/fixtures/build_source/foo/a.rb +0 -0
  292. data/spec/builder/fixtures/build_source/foo/b.rb +0 -0
  293. data/spec/builder/fixtures/build_source/foo/x.js +0 -0
  294. data/spec/builder/fixtures/build_source/foo/y.js +0 -0
  295. data/spec/builder/lib_name_for_spec.rb +0 -19
  296. data/test/index.min.html +0 -12
  297. data/test/spec_helper.rb +0 -4
data/.travis.yml CHANGED
@@ -5,7 +5,4 @@ rvm:
5
5
  - 1.9.3
6
6
 
7
7
  before_script:
8
- - "export DISPLAY=:99.0"
9
- - "sh -e /etc/init.d/xvfb start"
10
- - "bundle exec rake build dependencies spec"
11
-
8
+ - "bundle exec rake opal parser"
data/Gemfile CHANGED
@@ -3,15 +3,20 @@ source :rubygems
3
3
  gemspec
4
4
 
5
5
  gem "rake"
6
- gem "racc"
7
6
 
8
- group :browser do
7
+ # for rebuilding grammar.rb from grammar.y
8
+ group :grammar do
9
+ gem "racc"
10
+ end
11
+
12
+ # running tests on command line
13
+ group :testing do
14
+ gem "therubyracer", :require => 'v8'
9
15
  gem 'opal-spec', :git => 'git://github.com/adambeynon/opal-spec.git'
10
- gem 'opal-dom', :git => 'git://github.com/adambeynon/opal-dom.git'
11
- gem 'capybara'
12
16
  end
13
17
 
14
18
  group :docs do
15
19
  gem "redcarpet"
16
20
  gem "albino"
21
+ gem "rack"
17
22
  end
data/README.md CHANGED
@@ -1,610 +1,31 @@
1
1
  # Opal
2
2
 
3
- **Opal is a ruby to javascript compiler.** Opal aims to take ruby files
4
- and generate efficient javascript that maintains rubys features. Opal
5
- will, by default, generate fast and efficient code in preference to
6
- keeping all ruby features.
3
+ [![Build Status](https://secure.travis-ci.org/adambeynon/opal.png?branch=master)](http://travis-ci.org/adambeynon/opal)
7
4
 
8
- Opal comes with an implementation of the ruby corelib, written in ruby,
9
- that uses a bundled runtime (written in javascript) that tie all the
10
- features together. Whenever possible Opal bridges to native javascript
11
- features under the hood. The Opal gem includes the compiler used to
12
- convert ruby sources into javascript.
5
+ Opal is a ruby to javascript source-to-source compiler. It also has an
6
+ implementation of the ruby corelib.
13
7
 
14
8
  Opal is [hosted on github](http://github.com/adambeynon/opal), and there
15
9
  is a Freenode IRC channel at `#opal`.
16
10
 
17
- ## Downloads
18
-
19
- The Opal runtime and corelib are distributed here, and are required to
20
- run any code generated by opal.
21
-
22
- [Opal version 0.3.21](http://opalrb.org/opal.js) _(13.1kb Minified And Gzipped)_
23
-
24
- ## Installation
25
-
26
- Opal should be added to your Gemfile:
27
-
28
- ```ruby
29
- gem "opal"
30
- ```
31
-
32
11
  ## Usage
33
12
 
34
- The easiest way to use opal is to create a rake task using the
35
- `RakeTask` helper class. Assuming you have a single ruby file in
36
- your Opal app called `app.rb`:
37
-
38
- ```ruby
39
- # app.rb
40
- puts "Hello world"
41
- ```
42
-
43
- Then create a rake task similar to:
44
-
45
- ```ruby
46
- # Rakefile
47
- require 'opal/rake_task'
48
-
49
- Opal::RakeTask.new do |t|
50
- t.files = ['app.rb']
51
- end
52
- ```
53
-
54
- ### Building the app
55
-
56
- Building the app is as simple as running:
57
-
58
- ```
59
- rake opal:build
60
- ```
61
-
62
- This will build all your listed files into `build/app_name.js`. The
63
- output name is based on the directory name. This can be overriden by
64
- setting the `.name` property in the task:
65
-
66
- ```ruby
67
- Opal::RakeTask.new do |t|
68
- t.files = ['app.rb']
69
- t.name = 'my_awesome_app'
70
- end
71
- ```
72
-
73
- ### Building opal runtime
74
-
75
- To run the app in the browser, the opal runtime is required. This can
76
- be built using:
77
-
78
- ```
79
- rake opal:dependencies
80
- ```
81
-
82
- Which will build `opal.js` into `./build`.
83
-
84
- The output directory can also be overriden inside the rake task:
85
-
86
- ```ruby
87
- Opal::RakeTask.new do |t|
88
- t.files = ['app.rb']
89
- t.build_dir = 'out_dir'
90
- end
91
- ```
92
-
93
- The output directory will be created if it doesn't exist.
94
-
95
- ### Running the app
96
-
97
- The two compiled files need to be added to a html page so that they
98
- can run in the browser:
99
-
100
- ```html
101
- <!doctype html>
102
- <html>
103
- <head>
104
- <title>My awesome Opal app</title>
105
-
106
- <script src="build/opal.js"></script>
107
- <script src="build/my_awesome_app.js"></script>
108
-
109
- <script>
110
- // Run opal app
111
- Opal.require('app')
112
- </script>
113
- </head>
114
- <body>
115
- </body>
116
- </html>
117
- ```
118
-
119
- If you open the html file, observe the console and you should see
120
- `"Hello World"` printed to the console.
121
-
122
- It is necessary to run `Opal.require('app')` as all files built for
123
- opal are registered so that they can be required inside the ruby
124
- code.
125
-
126
- ### Adding dependencies
127
-
128
- The `opal:dependencies` rake task above can be used to build gems which
129
- are designed to run in the browser. `opal-dom` is a gem that given opal
130
- access to the DOM in the browser.
131
-
132
- `opal-dom` first needs to be installed as a gem (currently it is only
133
- available from git):
13
+ See the website, [http://opalrb.org](http://opalrb.org).
134
14
 
135
- ```ruby
136
- # Gemfile
137
- gem "opal"
138
- gem "opal-dom", :git => 'git://github.com/adambeynon/opal-dom.git'
139
- ```
15
+ ## Running tests
140
16
 
141
- Then add it to the dependencies to build:
17
+ Build the runtime, tests and dependencies:
142
18
 
143
- ```ruby
144
- Opal::RakeTask.new do |t|
145
- t.files = ['app.rb']
146
- t.dependencies = ['opal-dom']
147
- end
148
19
  ```
149
-
150
- Running `rake opal:dependencies` now will also build
151
- `build/opal-dom.js`.
152
-
153
- We can now update our application code:
154
-
155
- ```ruby
156
- # app.rb
157
- require 'opal-dom'
158
-
159
- alert "Hello!"
20
+ rake opal parser
160
21
  ```
161
22
 
162
- And rebuild:
23
+ Run tests using phantom.js runner:
163
24
 
164
25
  ```
165
- rake opal:build
26
+ rake test
166
27
  ```
167
28
 
168
- And add `opal-dom` to the html page:
169
-
170
- ```html
171
- <script src="build/opal.js"></script>
172
- <script src="build/opal-dom.js"></script>
173
- <script src="build/app.js"></script>
174
- ```
175
-
176
- Now running the app should cause an alert box to display.
177
-
178
- ## Features And Implementation
179
-
180
- Opal is a source-to-source compiler, so there is no VM as such and the
181
- compiled code aims to be as fast and efficient as possible, mapping
182
- directly to underlying javascript features and objects where possible.
183
-
184
- ### Literals
185
-
186
- **self** is always compiled to `self`. Any context inside the generated
187
- code is usually a function body; whether it be a method body, a block,
188
- a class/module body or the file itself.
189
-
190
- **true** and **false** are compiled directly into their native boolean
191
- equivalents. This makes interaction a lot easier as there is no need
192
- to convert values to opal specific values. It does mean that there is
193
- only a `Boolean` ruby class available, not seperate `TrueClass` and
194
- `FalseClass` classes.
195
-
196
- **nil** is compiled into a `nil` reference, which inside all generated
197
- files points to a special object which is just an instance of the ruby
198
- `NilClass` class. This object is available externally to javascript as
199
- `Opal.nil`.
200
-
201
- ```ruby
202
- nil # => nil
203
- true # => true
204
- false # => false
205
- self # => self
206
- ```
207
-
208
- #### Strings
209
-
210
- Ruby strings are compiled directly into javascript strings for
211
- performance as well as readability. This has the side effect that Opal
212
- does not support mutable strings - i.e. all strings are immutable.
213
-
214
- #### Symbols
215
-
216
- For performance reasons, symbols compile directly into strings. Opal
217
- supports all the symbol syntaxes, but does not have a real `Symbol`
218
- class. Symbols and Strings can therefore be used interchangeably.
219
-
220
- ```ruby
221
- "hello world!" # => "hello world!"
222
- :foo # => "foo"
223
- <<-EOS # => "\nHello there.\n"
224
- Hello there.
225
- EOS
226
- ```
227
-
228
- #### Numbers
229
-
230
- In Opal there is a single class for numbers; `Numeric`. To keep opal
231
- as performant as possible, ruby numbers are mapped to native numbers.
232
- This has the side effect that all numbers must be of the same class.
233
- Most relevant methods from `Integer`, `Float` and `Numeric` are
234
- implemented on this class.
235
-
236
- ```ruby
237
- 42 # => 42
238
- 3.142 # => 3.142
239
- ```
240
-
241
- #### Arrays
242
-
243
- Ruby arrays are compiled directly into javascript arrays. Special
244
- ruby syntaxes for word arrays etc are also supported.
245
-
246
- ```ruby
247
- [1, 2, 3, 4] # => [1, 2, 3, 4]
248
- %w[foo bar baz] # => ["foo", "bar", "baz"]
249
- ```
250
-
251
- #### Hash
252
-
253
- Inside a generated ruby script, a function `__hash` is available which
254
- creates a new hash. This is also available in javascript as `Opal.hash`
255
- and simply returns a new instance of the `Hash` class.
256
-
257
- ```ruby
258
- { :foo => 100, :baz => 700 } # => __hash("foo", 100, "baz", 700)
259
- { foo: 42, bar: [1, 2, 3] } # => __hash("foo", 42, "bar", [1, 2, 3])
260
- ```
261
-
262
- #### Range
263
-
264
- Similar to hash, there is a function `__range` available to create
265
- range instances.
266
-
267
- ```ruby
268
- 1..4 # => __range(1, 4, true)
269
- 3...7 # => __range(3, 7, false)
270
- ```
271
-
272
- #### Optimized Math Operators
273
-
274
- In ruby, all math operators are method calls, but compiling this into
275
- javascript would end up being too slow. For this reason, math
276
- operators are optimized to test first if the receiver is a number, and
277
- if so then to just carry out the math call.
278
-
279
- ```ruby
280
- 3 + 4
281
- ```
282
-
283
- This ruby code will then be compiled into the following javascript:
284
-
285
- ```javascript
286
- (a = 3, b = 4, typeof(a) === "number" ? a + b : /* method call */)
287
- ```
288
-
289
- This ternary statement falls back on sending a method to the receiver
290
- so all non-numeric receivers will still have the normal method call
291
- being sent. This optimization makes math operators a **lot faster**.
292
- Currently, the optimized method calls are `+`, `-`, `*` and `/`.
293
-
294
- ### method_missing
295
-
296
- Method missing is fully supported in Opal. It is implemented as
297
- efficiently as possible.
298
-
299
- ### Logic and conditionals
300
-
301
- As per ruby, Opal treats only `false` and `nil` as falsy, everything
302
- else is a truthy value including `""`, `0` and `[]`. This differs from
303
- javascript as these values are also treated as false.
304
-
305
- For this reason, most truthy tests must check if values are `false` or
306
- `nil`.
307
-
308
- Taking the following test:
309
-
310
- ```javascript
311
- val = 42
312
-
313
- if val
314
- return 3.142;
315
- end
316
- ```
317
-
318
- This would be compiled into:
319
-
320
- ```ruby
321
- val = 42;
322
-
323
- if (val !== false && val !== nil) {
324
- return 3.142;
325
- }
326
- ```
327
-
328
- This makes the generated truthy tests (`if` statements, `and` checks and
329
- `or` statements) a litle more verbose in the generated code.
330
-
331
- ### Instance variables
332
-
333
- Instance variables in Opal work just as expected. When ivars are set or
334
- retrieved on an object, they are set natively without the `@` prefix.
335
- This allows real javascript identifiers to be used which is more
336
- efficient then accessing variables by string name.
337
-
338
- ```ruby
339
- @foo = 200
340
- @foo # => 200
341
-
342
- @bar # => nil
343
- ```
344
-
345
- This gets compiled into:
346
-
347
- ```javascript
348
- this.foo = 200;
349
- this.foo; // => 200
350
-
351
- this.bar; // => nil
352
- ```
353
-
354
- The only point of warning is that when variables are used for the
355
- first time in ruby, they default to `nil`. In javascript, they default
356
- to `undefined`/`null`.
357
-
358
- To keep things working in opal, ivars must be preset to `nil` before
359
- they can be used. In the top scope and other corner cases, this needs
360
- to be done on a per scope basis, which can add overhead.
361
-
362
- To improve performance, once a class body is compiled, all ivars used
363
- within methods in that class are preset on the prototype of the class
364
- to be `nil`. This means that all known ivars are already set to nil,
365
- and this is done just once during the lifespan of the app.
366
-
367
- ```ruby
368
- class Foo
369
- def bar
370
- @lol
371
- end
372
-
373
- def woosh
374
- @kapow
375
- end
376
- end
377
- ```
378
-
379
- This example gets compiled into something similar to:
380
-
381
- ```javascript
382
- (function() {
383
- function Foo(){}
384
- // ...
385
-
386
- Foo.prototype.lol = Foo.prototype.woosh = nil;
387
-
388
- Foo.prototype.$bar = function() {
389
- return this.lol;
390
- };
391
-
392
- // etc ...
393
- })()
394
- ```
395
-
396
- ### Interacting with javascript
397
-
398
- Opal tries to interact as cleanly with javascript and its api as much
399
- as possible. Ruby arrays, strings, numbers, regexps, blocks and booleans
400
- are just javascript native equivalents. The only boxed core features are
401
- hashes and nil.
402
-
403
- As most of the corelib deals with these low level details, opal provides
404
- a special syntax for inlining javascript code. This is done with
405
- x-strings or "backticks", as their ruby use has no useful translation
406
- in the browser.
407
-
408
- ```ruby
409
- `window.title`
410
- # => "Opal: ruby to javascript compiler"
411
-
412
- %x{
413
- console.log("ruby version is:");
414
- console.log(#{ OPAL_VERSION });
415
- }
416
-
417
- # => ruby version is:
418
- # => 0.3.19
419
- ```
420
-
421
- Even interpolations are supported, as seen here.
422
-
423
- This feature of inlining code is used extensively, for example in
424
- Array#length:
425
-
426
- ```ruby
427
- class Array
428
- def length
429
- `this.length`
430
- end
431
- end
432
- ```
433
-
434
- X-Strings also have the ability to automatically return their value,
435
- as used by this example.
436
-
437
- ### Compiled Files
438
-
439
- As described above, a compiled ruby source gets generated into a string
440
- of javascript code that is wrapped inside an anonymous function. This
441
- looks similar to the following:
442
-
443
- ```javascript
444
- (function() {
445
- var nil = Opal.nil, self = Opal.top;
446
- // generated code
447
- })();
448
- ```
449
-
450
- Inside the function, `nil` is assigned to ensure a local copy is
451
- available, as well as all the helper methods used within the
452
- generated file. There is no return value from these functions as they
453
- are not used anywhere.
454
-
455
- As a complete example, assuming the following code:
456
-
457
- ```ruby
458
- puts "foo"
459
- ```
460
-
461
- This would compile directly into:
462
-
463
- ```javascript
464
- (function() {
465
- var nil = Opal.nil, self = Opal.top;
466
- self.$puts("foo");
467
- })();
468
- ```
469
-
470
- Most of the helpers are no longer present as they are not used in this
471
- example.
472
-
473
- ### Using compiled sources
474
-
475
- If you write the generated code as above into a file `app.js` and add
476
- that to your HTML page, then it is obvious that `"foo"` would be
477
- written to the browser's console.
478
-
479
- ### JSON
480
-
481
- The opal corelib includes JSON support instead of treating it as an
482
- external lib. The `JSON` module provides the usual parsing methods.
483
-
484
- ```ruby
485
- JSON.parse '{"a": 10, "b": [1, 2, 3], "c": null}'
486
- # => { "a" => 10, "b" => [1, 2, 3], "c" => nil }
487
- ```
488
-
489
- Opal expects `JSON` to be present in the browser, so older browsers
490
- may require a shim (json2.js) to work with opal. Most mobile browsers
491
- and modern desktop browsers include json support natively.
492
-
493
- ## Debugging and finding errors
494
-
495
- Because Opal does not aim to be fully compatible with ruby, there are
496
- some instances where things can break and it may not be entirely
497
- obvious what went wrong.
498
-
499
- ### Undefined methods
500
-
501
- By default, opal aims to be as fast as possible, so `method_missing` is
502
- not turned on by default. Instead, when calling a method that doesn't
503
- exist, a native error will be raised.
504
-
505
- ```ruby
506
- self.do_something()
507
- ```
508
-
509
- Might raise an error similar to:
510
-
511
- ```
512
- Error: 'undefined' is not a function (evaluating 'this.$do_something()')
513
- ```
514
-
515
- As described above, all ruby methods will have a `$` prefix which gives
516
- a good indication that it is a opal method that doesnt exist, and most
517
- js engines output the missing function name.
518
-
519
- ### Undefined constants
520
-
521
- If trying to access a constant that doesn't exist, there is no runtime
522
- error. Instead, the value of that expression is just `undefined` as
523
- constants are retrieved from objects that hold all constants in the
524
- scope. Trying to send a method to an undefined constant will therefore
525
- just raise an ugly javascript `TypeError`.
526
-
527
- If you are using the constant as a reference, it may not be until much
528
- later that the error occurs.
529
-
530
- ### Using javascript debuggers
531
-
532
- As opal just generates javascript, it is useful to use a native
533
- debugger to work through javascript code. To use a debugger, simply
534
- add an x-string similar to the following at the place you wish to
535
- debug:
536
-
537
- ```ruby
538
- # .. code
539
- `debugger`
540
- # .. more code
541
- ```
542
- The x-strings just pass the debugger statement straight through to the
543
- javascript output.
544
-
545
- Inside methods and blocks, the current `self` value is always the
546
- native `this` value. You will not see `self` inside debuggers as it is
547
- never used to refer to the actual ruby self value.
548
-
549
- All local variables and method/block arguments also keep their ruby
550
- names except in the rare cases when the name is reserved in javascript.
551
- In these cases, a `$` suffix is added to the name (e.g. `try` =>
552
- `try$`).
553
-
554
29
  ## License
555
30
 
556
- Opal is released under the MIT license.
557
-
558
- ## Change Log
559
-
560
- **0.3.21** _(16 July 2012)_
561
-
562
- * Add `method_missing` support to all objects and classes
563
- * Add `Opal.build_gem()` method to quickly build installed gem
564
- * Add `Opal.build_files()` method to build directories of files
565
-
566
- **0.3.20** _(23 June 2012)_
567
-
568
- * Merge JSON into core. JSON module and various #to_json methods are
569
- now included as part of corelib
570
- * Make `Time` class bridge to native `Date` constructor
571
- * Use named functions as class constuctors to make debugging easier
572
- * Classes are now real functions with prototypes. Bridged classes are
573
- now directly corresponding to the ruby class (e.g. Array === Opal.Array)
574
- * Set ivars used inside methods in class to `nil` inside class definition
575
- to avoid doing it everytime method is called
576
- * Add debug comments to output for def, class and module stating the file
577
- and line number the given code was generated from
578
-
579
- **0.3.19** _(30 May 2012)_
580
-
581
- * Add BasicObject as the root class
582
- * Add `Opal.define` and `Opal.require` for requiring files
583
- * Builder uses a `main` option to dictate which file to require on load
584
- * Completely revamp runtime to reduce helper methods
585
- * Allow native bridges (Array, String, etc) to be subclassed
586
- * Make sure `.js` files can be built with `Opal::Builder`
587
- * Include the current file name when raising parse errors
588
-
589
- **0.3.18** _(20 May 2012)_
590
-
591
- * Fix various core lib bugs
592
- * Completely remove `require` from corelib
593
- * Improve Builder to detect dependencies in files
594
-
595
- **0.3.17** _(19 May 2012)_
596
-
597
- * Revamp of Builder and Parser tools
598
- * Remove opal-repl
599
- * Added a lot of specs for core lib
600
-
601
- **0.3.16** _(15 January 2012)_
602
-
603
- * Added HEREDOCS support in parser
604
- * Parser now handles masgn (mass/multi assignments)
605
- * More useful DependencyBuilder class to build gems dependencies
606
- * Blocks no longer passed as an argument in method calls
607
-
608
- **0.3.15**
609
-
610
- * Initial Release.
31
+ Opal is released under the MIT license.