opal 0.3.21 → 0.3.22

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 (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.