opal 0.8.1 → 0.9.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (331) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -2
  3. data/.gitmodules +3 -3
  4. data/.jshintrc +17 -20
  5. data/.travis.yml +22 -11
  6. data/CHANGELOG.md +51 -1
  7. data/CODE_OF_CONDUCT.md +15 -0
  8. data/CONTRIBUTING.md +125 -9
  9. data/Gemfile +1 -1
  10. data/Guardfile +2 -2
  11. data/README.md +95 -29
  12. data/Rakefile +1 -1
  13. data/benchmark/benchmarks +103 -0
  14. data/benchmark/bm_array_flatten.rb +9 -0
  15. data/benchmark/bm_array_intersection_numbers.rb +7 -0
  16. data/benchmark/bm_array_intersection_objects.rb +7 -0
  17. data/benchmark/bm_array_intersection_strings.rb +7 -0
  18. data/benchmark/bm_array_join_ary.rb +9 -0
  19. data/benchmark/bm_array_minus_numbers.rb +7 -0
  20. data/benchmark/bm_array_minus_objects.rb +7 -0
  21. data/benchmark/bm_array_minus_strings.rb +7 -0
  22. data/benchmark/bm_array_union_numbers.rb +7 -0
  23. data/benchmark/bm_array_union_objects.rb +7 -0
  24. data/benchmark/bm_array_union_strings.rb +7 -0
  25. data/benchmark/bm_array_uniq_bang_numbers.rb +5 -0
  26. data/benchmark/bm_array_uniq_bang_objects.rb +5 -0
  27. data/benchmark/bm_array_uniq_bang_strings.rb +5 -0
  28. data/benchmark/bm_array_uniq_numbers.rb +5 -0
  29. data/benchmark/bm_array_uniq_objects.rb +5 -0
  30. data/benchmark/bm_array_uniq_strings.rb +5 -0
  31. data/benchmark/bm_dispatch_bind_table.rb +57 -0
  32. data/benchmark/bm_dispatch_code_gen.rb +65 -0
  33. data/benchmark/bm_dispatch_code_gen_if.rb +64 -0
  34. data/benchmark/bm_dispatch_hardcoded.rb +44 -0
  35. data/benchmark/bm_dispatch_send.rb +38 -0
  36. data/benchmark/bm_dispatch_send_table.rb +57 -0
  37. data/benchmark/bm_hash_assoc_object.rb +11 -0
  38. data/benchmark/bm_hash_assoc_string.rb +9 -0
  39. data/benchmark/bm_hash_clone_object.rb +9 -0
  40. data/benchmark/bm_hash_clone_string.rb +9 -0
  41. data/benchmark/bm_hash_delete_object.rb +11 -0
  42. data/benchmark/bm_hash_delete_string.rb +9 -0
  43. data/benchmark/bm_hash_each_key_object.rb +9 -0
  44. data/benchmark/bm_hash_each_key_string.rb +9 -0
  45. data/benchmark/bm_hash_each_object.rb +9 -0
  46. data/benchmark/bm_hash_each_string.rb +9 -0
  47. data/benchmark/bm_hash_each_value_object.rb +9 -0
  48. data/benchmark/bm_hash_each_value_string.rb +9 -0
  49. data/benchmark/bm_hash_element_reference_object.rb +11 -0
  50. data/benchmark/bm_hash_element_reference_string.rb +9 -0
  51. data/benchmark/bm_hash_element_set_object.rb +5 -0
  52. data/benchmark/bm_hash_element_set_string.rb +5 -0
  53. data/benchmark/bm_hash_equal_value_object.rb +14 -0
  54. data/benchmark/bm_hash_equal_value_string.rb +11 -0
  55. data/benchmark/bm_hash_fetch_object.rb +11 -0
  56. data/benchmark/bm_hash_fetch_string.rb +9 -0
  57. data/benchmark/bm_hash_flatten_object.rb +9 -0
  58. data/benchmark/bm_hash_flatten_string.rb +9 -0
  59. data/benchmark/bm_hash_has_key_object.rb +11 -0
  60. data/benchmark/bm_hash_has_key_string.rb +9 -0
  61. data/benchmark/bm_hash_has_value_object.rb +9 -0
  62. data/benchmark/bm_hash_has_value_string.rb +9 -0
  63. data/benchmark/bm_hash_hash_object.rb +9 -0
  64. data/benchmark/bm_hash_hash_string.rb +9 -0
  65. data/benchmark/bm_hash_inspect_object.rb +9 -0
  66. data/benchmark/bm_hash_inspect_string.rb +9 -0
  67. data/benchmark/bm_hash_invert_object.rb +9 -0
  68. data/benchmark/bm_hash_invert_string.rb +9 -0
  69. data/benchmark/bm_hash_keep_if_object.rb +9 -0
  70. data/benchmark/bm_hash_keep_if_string.rb +9 -0
  71. data/benchmark/bm_hash_key_object.rb +9 -0
  72. data/benchmark/bm_hash_key_string.rb +9 -0
  73. data/benchmark/bm_hash_keys_object.rb +9 -0
  74. data/benchmark/bm_hash_keys_string.rb +9 -0
  75. data/benchmark/bm_hash_literal_mixed_large.rb +3 -0
  76. data/benchmark/bm_hash_literal_mixed_small.rb +3 -0
  77. data/benchmark/bm_hash_literal_object_large.rb +4 -0
  78. data/benchmark/bm_hash_literal_object_small.rb +3 -0
  79. data/benchmark/bm_hash_literal_string_large.rb +4 -0
  80. data/benchmark/bm_hash_literal_string_small.rb +3 -0
  81. data/benchmark/bm_hash_merge_object.rb +22 -0
  82. data/benchmark/bm_hash_merge_string.rb +18 -0
  83. data/benchmark/bm_hash_rassoc_object.rb +9 -0
  84. data/benchmark/bm_hash_rassoc_string.rb +9 -0
  85. data/benchmark/bm_hash_rehash_object.rb +9 -0
  86. data/benchmark/bm_hash_rehash_string.rb +9 -0
  87. data/benchmark/bm_hash_reject_bang_object.rb +9 -0
  88. data/benchmark/bm_hash_reject_bang_string.rb +9 -0
  89. data/benchmark/bm_hash_reject_object.rb +9 -0
  90. data/benchmark/bm_hash_reject_string.rb +9 -0
  91. data/benchmark/bm_hash_replace_object.rb +18 -0
  92. data/benchmark/bm_hash_replace_string.rb +14 -0
  93. data/benchmark/bm_hash_select_bang_object.rb +9 -0
  94. data/benchmark/bm_hash_select_bang_string.rb +9 -0
  95. data/benchmark/bm_hash_select_object.rb +9 -0
  96. data/benchmark/bm_hash_select_string.rb +9 -0
  97. data/benchmark/bm_hash_shift_object.rb +10 -0
  98. data/benchmark/bm_hash_shift_string.rb +10 -0
  99. data/benchmark/bm_hash_to_a_object.rb +9 -0
  100. data/benchmark/bm_hash_to_a_string.rb +9 -0
  101. data/benchmark/bm_hash_to_h_object.rb +10 -0
  102. data/benchmark/bm_hash_to_h_string.rb +10 -0
  103. data/benchmark/bm_hash_values_object.rb +9 -0
  104. data/benchmark/bm_hash_values_string.rb +9 -0
  105. data/benchmark/run.rb +48 -0
  106. data/bin/opal-mspec +1 -1
  107. data/bin/opal-repl +4 -4
  108. data/docs/compiled_ruby.md +214 -56
  109. data/docs/configuring_gems.md +2 -2
  110. data/docs/faq.md +2 -2
  111. data/docs/getting_started.md +19 -2
  112. data/docs/jquery.md +5 -5
  113. data/docs/opal_parser.md +53 -0
  114. data/docs/unsupported_features.md +2 -2
  115. data/docs/upgrading.md +22 -0
  116. data/docs/using_sprockets.md +15 -0
  117. data/examples/rack/config.ru +13 -0
  118. data/examples/sinatra/config.ru +4 -5
  119. data/lib/mspec/opal/runner.rb +54 -11
  120. data/lib/opal.rb +1 -1
  121. data/lib/opal/builder.rb +1 -1
  122. data/lib/opal/builder_processors.rb +1 -1
  123. data/lib/opal/cli.rb +17 -13
  124. data/lib/opal/cli_options.rb +1 -1
  125. data/lib/opal/compiler.rb +12 -0
  126. data/lib/opal/config.rb +4 -0
  127. data/lib/opal/nodes/arglist.rb +5 -7
  128. data/lib/opal/nodes/call.rb +6 -1
  129. data/lib/opal/nodes/call_special.rb +74 -0
  130. data/lib/opal/nodes/def.rb +35 -28
  131. data/lib/opal/nodes/definitions.rb +3 -5
  132. data/lib/opal/nodes/for.rb +13 -0
  133. data/lib/opal/nodes/helpers.rb +15 -1
  134. data/lib/opal/nodes/if.rb +5 -5
  135. data/lib/opal/nodes/iter.rb +6 -1
  136. data/lib/opal/nodes/literal.rb +1 -1
  137. data/lib/opal/nodes/logic.rb +2 -2
  138. data/lib/opal/nodes/masgn.rb +1 -2
  139. data/lib/opal/nodes/module.rb +2 -1
  140. data/lib/opal/nodes/rescue.rb +10 -1
  141. data/lib/opal/nodes/scope.rb +8 -2
  142. data/lib/opal/nodes/singleton_class.rb +1 -1
  143. data/lib/opal/nodes/top.rb +11 -0
  144. data/lib/opal/nodes/variables.rb +4 -4
  145. data/lib/opal/parser.rb +21 -3
  146. data/lib/opal/parser/grammar.rb +3115 -2961
  147. data/lib/opal/parser/grammar.y +29 -6
  148. data/lib/opal/parser/lexer.rb +18 -8
  149. data/lib/opal/sprockets.rb +85 -0
  150. data/lib/opal/sprockets/processor.rb +11 -35
  151. data/lib/opal/sprockets/server.rb +3 -15
  152. data/lib/opal/version.rb +2 -2
  153. data/opal.gemspec +4 -4
  154. data/opal/README.md +9 -0
  155. data/opal/corelib/array.rb +433 -181
  156. data/opal/corelib/basic_object.rb +48 -4
  157. data/opal/corelib/boolean.rb +15 -6
  158. data/opal/corelib/class.rb +6 -5
  159. data/opal/corelib/comparable.rb +12 -0
  160. data/opal/corelib/complex.rb +282 -0
  161. data/opal/corelib/constants.rb +9 -0
  162. data/opal/corelib/enumerable.rb +83 -34
  163. data/opal/corelib/enumerator.rb +3 -1
  164. data/opal/corelib/error.rb +49 -10
  165. data/opal/corelib/file.rb +1 -0
  166. data/opal/corelib/hash.rb +353 -577
  167. data/opal/corelib/helpers.rb +20 -0
  168. data/opal/corelib/kernel.rb +114 -59
  169. data/opal/corelib/math.rb +470 -0
  170. data/opal/corelib/method.rb +11 -2
  171. data/opal/corelib/module.rb +96 -96
  172. data/opal/corelib/{nil_class.rb → nil.rb} +20 -1
  173. data/opal/corelib/number.rb +751 -0
  174. data/opal/corelib/numeric.rb +77 -437
  175. data/opal/corelib/proc.rb +81 -1
  176. data/opal/corelib/process.rb +27 -0
  177. data/opal/corelib/rational.rb +358 -0
  178. data/opal/corelib/regexp.rb +156 -27
  179. data/opal/corelib/runtime.js +724 -335
  180. data/opal/corelib/string.rb +93 -104
  181. data/opal/corelib/string/encoding.rb +177 -0
  182. data/opal/corelib/string/inheritance.rb +2 -0
  183. data/opal/corelib/struct.rb +105 -18
  184. data/opal/corelib/time.rb +267 -146
  185. data/opal/corelib/unsupported.rb +216 -0
  186. data/opal/corelib/variables.rb +0 -6
  187. data/opal/opal.rb +8 -22
  188. data/opal/opal/base.rb +9 -0
  189. data/opal/opal/mini.rb +17 -0
  190. data/spec/README.md +1 -1
  191. data/spec/filters/bugs/array.rb +38 -136
  192. data/spec/filters/bugs/{basic_object.rb → basicobject.rb} +14 -15
  193. data/spec/filters/bugs/class.rb +6 -12
  194. data/spec/filters/bugs/complex.rb +3 -0
  195. data/spec/filters/bugs/date.rb +162 -10
  196. data/spec/filters/bugs/enumerable.rb +31 -58
  197. data/spec/filters/bugs/enumerator.rb +42 -0
  198. data/spec/filters/bugs/exception.rb +66 -10
  199. data/spec/filters/bugs/float.rb +17 -0
  200. data/spec/filters/bugs/hash.rb +11 -97
  201. data/spec/filters/bugs/inheritance.rb +5 -0
  202. data/spec/filters/bugs/integer.rb +28 -0
  203. data/spec/filters/bugs/kernel.rb +304 -12
  204. data/spec/filters/bugs/language.rb +133 -399
  205. data/spec/filters/bugs/language_opal.rb +88 -0
  206. data/spec/filters/bugs/module.rb +203 -62
  207. data/spec/filters/bugs/numeric.rb +32 -0
  208. data/spec/filters/bugs/proc.rb +39 -0
  209. data/spec/filters/bugs/range.rb +148 -0
  210. data/spec/filters/bugs/regexp.rb +168 -0
  211. data/spec/filters/bugs/set.rb +46 -3
  212. data/spec/filters/bugs/singleton.rb +1 -2
  213. data/spec/filters/bugs/string.rb +59 -90
  214. data/spec/filters/bugs/strscan.rb +80 -0
  215. data/spec/filters/bugs/struct.rb +10 -20
  216. data/spec/filters/bugs/time.rb +17 -184
  217. data/spec/filters/bugs/unboundmethod.rb +22 -0
  218. data/spec/filters/unsupported/array.rb +163 -0
  219. data/spec/filters/unsupported/basicobject.rb +14 -0
  220. data/spec/filters/unsupported/bignum.rb +46 -0
  221. data/spec/filters/unsupported/class.rb +4 -0
  222. data/spec/filters/unsupported/delegator.rb +5 -0
  223. data/spec/filters/unsupported/enumerable.rb +11 -0
  224. data/spec/filters/unsupported/enumerator.rb +8 -9
  225. data/spec/filters/unsupported/fixnum.rb +14 -0
  226. data/spec/filters/unsupported/float.rb +41 -7
  227. data/spec/filters/unsupported/freeze.rb +45 -0
  228. data/spec/filters/unsupported/hash.rb +50 -0
  229. data/spec/filters/unsupported/integer.rb +3 -0
  230. data/spec/filters/unsupported/kernel.rb +31 -0
  231. data/spec/filters/unsupported/language.rb +17 -0
  232. data/spec/filters/unsupported/matchdata.rb +30 -0
  233. data/spec/filters/unsupported/math.rb +3 -0
  234. data/spec/filters/unsupported/module.rb +5 -3
  235. data/spec/filters/unsupported/pathname.rb +3 -0
  236. data/spec/filters/unsupported/privacy.rb +136 -0
  237. data/spec/filters/unsupported/proc.rb +3 -0
  238. data/spec/filters/unsupported/regexp.rb +59 -0
  239. data/spec/filters/unsupported/set.rb +4 -0
  240. data/spec/filters/unsupported/{marshal.rb → singleton.rb} +4 -2
  241. data/spec/filters/unsupported/{mutable_strings.rb → string.rb} +456 -336
  242. data/spec/filters/unsupported/struct.rb +3 -0
  243. data/spec/filters/unsupported/symbol.rb +5 -0
  244. data/spec/filters/unsupported/taint.rb +16 -0
  245. data/spec/filters/unsupported/thread.rb +5 -0
  246. data/spec/filters/unsupported/time.rb +197 -16
  247. data/spec/lib/cli_spec.rb +14 -4
  248. data/spec/lib/compiler_spec.rb +9 -1
  249. data/spec/lib/parser/call_spec.rb +18 -0
  250. data/spec/lib/parser/not_spec.rb +2 -8
  251. data/spec/lib/sprockets_spec.rb +24 -0
  252. data/spec/opal/core/array/intersection_spec.rb +38 -0
  253. data/spec/opal/core/array/minus_spec.rb +38 -0
  254. data/spec/opal/core/array/union_spec.rb +38 -0
  255. data/spec/opal/core/array/uniq_spec.rb +49 -0
  256. data/spec/opal/core/exception_spec.rb +7 -0
  257. data/spec/opal/core/fixtures/require_tree_with_dot/file 1.rb +1 -0
  258. data/spec/opal/core/fixtures/require_tree_with_dot/file 2.rb +1 -0
  259. data/spec/opal/core/fixtures/require_tree_with_dot/file 3.rb +1 -0
  260. data/spec/opal/core/fixtures/require_tree_with_dot/index.rb +3 -0
  261. data/spec/opal/core/hash/internals_spec.rb +332 -0
  262. data/spec/opal/core/helpers_spec.rb +14 -0
  263. data/spec/opal/core/kernel/freeze_spec.rb +1 -1
  264. data/spec/opal/core/kernel/raise_spec.rb +13 -0
  265. data/spec/opal/core/kernel/require_tree_spec.rb +9 -0
  266. data/spec/opal/core/language/class_spec.rb +55 -0
  267. data/spec/opal/core/language/fixtures/send.rb +1 -0
  268. data/spec/opal/core/language/keyword_arguments_spec.rb +11 -0
  269. data/spec/opal/core/language/send_spec.rb +5 -0
  270. data/spec/opal/core/method/to_proc_spec.rb +28 -0
  271. data/spec/opal/core/module/name_spec.rb +0 -17
  272. data/spec/opal/core/runtime/bridged_classes_spec.rb +2 -2
  273. data/spec/opal/core/runtime/eval_spec.rb +1 -1
  274. data/spec/opal/core/runtime/method_missing_spec.rb +6 -0
  275. data/spec/opal/core/runtime_spec.rb +51 -0
  276. data/spec/opal/stdlib/js_spec.rb +66 -0
  277. data/spec/opal/stdlib/native/hash_spec.rb +36 -0
  278. data/spec/rubyspecs +152 -273
  279. data/spec/spec_helper.rb +10 -11
  280. data/stdlib/base64.rb +9 -9
  281. data/stdlib/benchmark.rb +551 -4
  282. data/stdlib/console.rb +94 -0
  283. data/stdlib/date.rb +1 -1
  284. data/stdlib/encoding.rb +1 -170
  285. data/stdlib/js.rb +56 -0
  286. data/stdlib/json.rb +9 -14
  287. data/stdlib/math.rb +1 -370
  288. data/stdlib/native.rb +133 -63
  289. data/stdlib/nodejs/file.rb +5 -0
  290. data/stdlib/nodejs/fileutils.rb +13 -6
  291. data/stdlib/nodejs/node_modules/js-yaml/node_modules/argparse/README.md +1 -1
  292. data/stdlib/opal-parser.rb +1 -2
  293. data/stdlib/ostruct.rb +65 -6
  294. data/stdlib/pp.rb +2 -4
  295. data/stdlib/rbconfig.rb +1 -3
  296. data/stdlib/strscan.rb +164 -28
  297. data/tasks/benchmarking.rake +88 -0
  298. data/tasks/testing.rake +181 -55
  299. data/{lib/mspec/opal/special_calls.rb → tasks/testing/mspec_special_calls.rb} +1 -1
  300. data/{lib/mspec/opal/sprockets.js → tasks/testing/phantomjs1-sprockets.js} +17 -6
  301. data/test/opal/test_keyword.rb +590 -0
  302. data/vendored-minitest/minitest.rb +2 -2
  303. data/vendored-minitest/test/unit.rb +5 -0
  304. metadata +229 -62
  305. data/benchmarks/operators.rb +0 -11
  306. data/benchmarks/prova.js.rb +0 -13
  307. data/docs/libraries.md +0 -36
  308. data/lib/mspec/opal/new.html.erb +0 -1
  309. data/lib/mspec/opal/rake_task.rb +0 -248
  310. data/opal/corelib/match_data.rb +0 -128
  311. data/spec/filters/bugs/math.rb +0 -95
  312. data/spec/filters/bugs/nil.rb +0 -7
  313. data/spec/filters/bugs/opal.rb +0 -9
  314. data/spec/filters/bugs/regular_expressions.rb +0 -41
  315. data/spec/filters/bugs/stringscanner.rb +0 -33
  316. data/spec/filters/unsupported/encoding.rb +0 -102
  317. data/spec/filters/unsupported/frozen.rb +0 -92
  318. data/spec/filters/unsupported/hash_compare_by_identity.rb +0 -16
  319. data/spec/filters/unsupported/integer_size.rb +0 -59
  320. data/spec/filters/unsupported/method_added.rb +0 -10
  321. data/spec/filters/unsupported/private_constants.rb +0 -30
  322. data/spec/filters/unsupported/private_methods.rb +0 -55
  323. data/spec/filters/unsupported/random.rb +0 -4
  324. data/spec/filters/unsupported/rational_numbers.rb +0 -4
  325. data/spec/filters/unsupported/regular_expressions.rb +0 -137
  326. data/spec/filters/unsupported/ruby_exe.rb +0 -5
  327. data/spec/filters/unsupported/symbols.rb +0 -17
  328. data/spec/filters/unsupported/tainted.rb +0 -180
  329. data/spec/filters/unsupported/trusted.rb +0 -88
  330. data/stdlib/process.rb +0 -10
  331. data/tasks/documenting.rake +0 -37
@@ -0,0 +1,9 @@
1
+ h = {}
2
+
3
+ 10_000.times do |i|
4
+ h[i.to_s] = nil
5
+ end
6
+
7
+ 1_000.times do
8
+ h.rehash
9
+ end
@@ -0,0 +1,9 @@
1
+ h = {}
2
+
3
+ 10_000.times do |i|
4
+ h[Object.new] = i
5
+ end
6
+
7
+ 10_000.times do |i|
8
+ h.reject!{|k, v| v <= i}
9
+ end
@@ -0,0 +1,9 @@
1
+ h = {}
2
+
3
+ 10_000.times do |i|
4
+ h[i.to_s] = i
5
+ end
6
+
7
+ 10_000.times do |i|
8
+ h.reject!{|k, v| v <= i}
9
+ end
@@ -0,0 +1,9 @@
1
+ h = {}
2
+
3
+ 10_000.times do |i|
4
+ h[Object.new] = i
5
+ end
6
+
7
+ 100.times do |i|
8
+ h.reject{|k, v| v % 2 == 0}
9
+ end
@@ -0,0 +1,9 @@
1
+ h = {}
2
+
3
+ 10_000.times do |i|
4
+ h[i.to_s] = i
5
+ end
6
+
7
+ 100.times do |i|
8
+ h.reject{|k, v| v % 2 == 0}
9
+ end
@@ -0,0 +1,18 @@
1
+ h1 = {}
2
+ h2 = {}
3
+
4
+ a = []
5
+
6
+ 1.upto(5_000) do |i|
7
+ a[i] = Object.new
8
+ h1[a[i]] = nil
9
+ end
10
+
11
+ 2_501.upto(7_500) do |i|
12
+ a[i] = Object.new
13
+ h2[a[i]] = nil
14
+ end
15
+
16
+ 1_000.times do
17
+ h1.replace(h2)
18
+ end
@@ -0,0 +1,14 @@
1
+ h1 = {}
2
+ h2 = {}
3
+
4
+ 1.upto(5_000) do |i|
5
+ h1[i.to_s] = nil
6
+ end
7
+
8
+ 2_501.upto(7_500) do |i|
9
+ h2[i.to_s] = nil
10
+ end
11
+
12
+ 1_000.times do
13
+ h1.replace(h2)
14
+ end
@@ -0,0 +1,9 @@
1
+ h = {}
2
+
3
+ 10_000.times do |i|
4
+ h[Object.new] = i
5
+ end
6
+
7
+ 10_000.times do |i|
8
+ h.select!{|k, v| v > i}
9
+ end
@@ -0,0 +1,9 @@
1
+ h = {}
2
+
3
+ 10_000.times do |i|
4
+ h[i.to_s] = i
5
+ end
6
+
7
+ 10_000.times do |i|
8
+ h.select!{|k, v| v > i}
9
+ end
@@ -0,0 +1,9 @@
1
+ h = {}
2
+
3
+ 10_000.times do |i|
4
+ h[Object.new] = i
5
+ end
6
+
7
+ 100.times do |i|
8
+ h.select{|k, v| v % 2 == 0}
9
+ end
@@ -0,0 +1,9 @@
1
+ h = {}
2
+
3
+ 10_000.times do |i|
4
+ h[i.to_s] = i
5
+ end
6
+
7
+ 100.times do |i|
8
+ h.select{|k, v| v % 2 == 0}
9
+ end
@@ -0,0 +1,10 @@
1
+ h = {}
2
+
3
+ 10_000.times do |i|
4
+ h[Object.new] = nil
5
+ end
6
+
7
+ 1_000_000.times do
8
+ k, v = h.shift
9
+ h[k] = v
10
+ end
@@ -0,0 +1,10 @@
1
+ h = {}
2
+
3
+ 10_000.times do |i|
4
+ h[i.to_s] = nil
5
+ end
6
+
7
+ 1_000_000.times do
8
+ k, v = h.shift
9
+ h[k] = v
10
+ end
@@ -0,0 +1,9 @@
1
+ h = {}
2
+
3
+ 10_000.times do |i|
4
+ h[Object.new] = nil
5
+ end
6
+
7
+ 5_000.times do
8
+ h.to_a
9
+ end
@@ -0,0 +1,9 @@
1
+ h = {}
2
+
3
+ 10_000.times do |i|
4
+ h[i.to_s] = nil
5
+ end
6
+
7
+ 5_000.times do
8
+ h.to_a
9
+ end
@@ -0,0 +1,10 @@
1
+ class MyHash < Hash; end
2
+ h = MyHash.new
3
+
4
+ 10_000.times do |i|
5
+ h[Object.new] = nil
6
+ end
7
+
8
+ 1_000.times do
9
+ h.to_h
10
+ end
@@ -0,0 +1,10 @@
1
+ class MyHash < Hash; end
2
+ h = MyHash.new
3
+
4
+ 10_000.times do |i|
5
+ h[i.to_s] = nil
6
+ end
7
+
8
+ 1_000.times do
9
+ h.to_h
10
+ end
@@ -0,0 +1,9 @@
1
+ h = {}
2
+
3
+ 10_000.times do |i|
4
+ h[Object.new] = nil
5
+ end
6
+
7
+ 1_000.times do
8
+ h.values
9
+ end
@@ -0,0 +1,9 @@
1
+ h = {}
2
+
3
+ 10_000.times do |i|
4
+ h[i.to_s] = nil
5
+ end
6
+
7
+ 1_000.times do
8
+ h.values
9
+ end
data/benchmark/run.rb ADDED
@@ -0,0 +1,48 @@
1
+ if RUBY_ENGINE == 'opal'
2
+ require 'opal/compiler'
3
+ require 'nodejs'
4
+ end
5
+
6
+ BEST_OF_N = Integer(ENV['BEST_OF_N']) rescue 1
7
+
8
+ require 'benchmark'
9
+
10
+ files = ARGV
11
+
12
+ if files.empty?
13
+ files = File.read('benchmark/benchmarks').lines.map(&:strip).reject do |line|
14
+ line.empty? || line.start_with?('#')
15
+ end
16
+ end
17
+
18
+ maxlen = files.max_by{|file| file.length}.length + 1
19
+
20
+ total_time = 0
21
+
22
+ files.each do |file|
23
+ print file, " " * (maxlen - file.length)
24
+
25
+ times = []
26
+
27
+ if RUBY_ENGINE == 'opal'
28
+ code = Opal.compile(File.read(file))
29
+ BEST_OF_N.times do
30
+ times << Benchmark.measure { `eval(code)` }
31
+ end
32
+ else
33
+ code = File.read(file)
34
+ BEST_OF_N.times do
35
+ times << Benchmark.measure { eval(code) }
36
+ end
37
+ end
38
+
39
+ time = times.min_by{|t| t.real}
40
+
41
+ total_time += time.real
42
+
43
+ print time.real, "\n"
44
+ end
45
+
46
+ bottom_line = "Executed #{ files.length } benchmark#{ 's' if files.length != 1} in #{ total_time } sec"
47
+ $stderr.print "=" * bottom_line.length, "\n"
48
+ $stderr.print bottom_line, "\n"
data/bin/opal-mspec CHANGED
@@ -7,4 +7,4 @@ pattern = %Q{MSPEC_PATTERN="{#{specs.join(',')}}"} if specs.any?
7
7
  command = [pattern, 'rake mspec'].compact.join(' ')
8
8
  exec command
9
9
 
10
- # RUBYOPT="-rbundler/setup -rmspec/opal/special_calls" bundle exec mspec run -t opal -pspec/corelib/spec_helper spec/corelib/core/true/*
10
+ # RUBYOPT="-rbundler/setup -rmspec/opal/special_calls" bundle exec mspec run -t opal -pspec/rubyspec/spec_helper spec/rubyspec/core/true/*
data/bin/opal-repl CHANGED
@@ -14,7 +14,7 @@ module Opal
14
14
  begin
15
15
  require 'v8'
16
16
  rescue LoadError
17
- abort 'therubyracer must be installed'
17
+ abort 'opal-repl depends on therubyracer gem, which is not currently installed'
18
18
  end
19
19
 
20
20
  @v8 = V8::Context.new
@@ -41,11 +41,11 @@ module Opal
41
41
 
42
42
  loop do
43
43
  # on SIGINT lets just return from the loop..
44
- trap("SIGINT") { finish; return }
44
+ trap('SIGINT') { finish; return }
45
45
  line = Readline.readline '>> ', true
46
46
 
47
47
  # if we type exit, then we need to close down context
48
- if line == "exit" or line.nil?
48
+ if line == 'exit' or line.nil?
49
49
  break
50
50
  end
51
51
 
@@ -57,7 +57,7 @@ module Opal
57
57
 
58
58
  def eval_ruby(str)
59
59
  code = Opal::Builder.new.build_str(str, '(irb)', :irb => true, :const_missing => true)
60
- code.processed[0...-1].each{ |c| @v8.eval(c.to_s) }
60
+ code.processed[0...-1].each { |c| @v8.eval(c.to_s) }
61
61
  @v8.eval "var $_result = #{code.processed.last.to_s} ($_result == null ? 'nil' : $_result.$inspect());"
62
62
  rescue => e
63
63
  puts "#{e.message}\n\t#{e.backtrace.join("\n\t")}"
@@ -1,6 +1,6 @@
1
1
  # Compiled Ruby Code
2
2
 
3
- ## Generated Javascript
3
+ ## Generated JavaScript
4
4
 
5
5
  Opal is a source-to-source compiler, so there is no VM as such and the
6
6
  compiled code aims to be as fast and efficient as possible, mapping
@@ -43,11 +43,11 @@ Hello there.
43
43
  EOS
44
44
  ```
45
45
 
46
- Ruby strings are compiled directly into javascript strings for
46
+ Ruby strings are compiled directly into JavaScript strings for
47
47
  performance as well as readability. This has the side effect that Opal
48
48
  does not support mutable strings - i.e. all strings are immutable.
49
49
 
50
- NOTE: Strings in Opal are immutable because they are compiled into regular javascript strings. This is done for performance reasons.
50
+ NOTE: Strings in Opal are immutable because they are compiled into regular JavaScript strings. This is done for performance reasons.
51
51
 
52
52
  For performance reasons, symbols are also compiled directly into strings.
53
53
  Opal supports all the symbol syntaxes, but does not have a real `Symbol`
@@ -55,8 +55,8 @@ class. Symbols and Strings can therefore be used interchangeably.
55
55
 
56
56
  #### Numbers
57
57
 
58
- In Opal there is a single class for numbers; `Numeric`. To keep opal
59
- as performant as possible, ruby numbers are mapped to native numbers.
58
+ In Opal there is a single class for numbers; `Numeric`. To keep Opal
59
+ as performant as possible, Ruby numbers are mapped to native numbers.
60
60
  This has the side effect that all numbers must be of the same class.
61
61
  Most relevant methods from `Integer`, `Float` and `Numeric` are
62
62
  implemented on this class.
@@ -68,8 +68,8 @@ implemented on this class.
68
68
 
69
69
  #### Arrays
70
70
 
71
- Ruby arrays are compiled directly into javascript arrays. Special
72
- ruby syntaxes for word arrays etc are also supported.
71
+ Ruby arrays are compiled directly into JavaScript arrays. Special
72
+ Ruby syntaxes for word arrays etc are also supported.
73
73
 
74
74
  ```ruby
75
75
  [1, 2, 3, 4] # => [1, 2, 3, 4]
@@ -78,30 +78,30 @@ ruby syntaxes for word arrays etc are also supported.
78
78
 
79
79
  #### Hash
80
80
 
81
- Inside a generated ruby script, a function `__hash` is available which
82
- creates a new hash. This is also available in javascript as `Opal.hash`
81
+ Inside a generated Ruby script, a function `Opal.hash` is available which
82
+ creates a new hash. This is also available in JavaScript as `Opal.hash`
83
83
  and simply returns a new instance of the `Hash` class.
84
84
 
85
85
  ```ruby
86
- { :foo => 100, :baz => 700 } # => __hash("foo", 100, "baz", 700)
87
- { foo: 42, bar: [1, 2, 3] } # => __hash("foo", 42, "bar", [1, 2, 3])
86
+ { :foo => 100, :baz => 700 } # => Opal.hash("foo", 100, "baz", 700)
87
+ { foo: 42, bar: [1, 2, 3] } # => Opal.hash("foo", 42, "bar", [1, 2, 3])
88
88
  ```
89
89
 
90
90
  #### Range
91
91
 
92
- Similar to hash, there is a function `__range` available to create
92
+ Similar to hash, there is a function `Opal.range` available to create
93
93
  range instances.
94
94
 
95
95
  ```ruby
96
- 1..4 # => __range(1, 4, true)
97
- 3...7 # => __range(3, 7, false)
96
+ 1..4 # => Opal.range(1, 4, true)
97
+ 3...7 # => Opal.range(3, 7, false)
98
98
  ```
99
99
 
100
100
  ### Logic and conditionals
101
101
 
102
- As per ruby, Opal treats only `false` and `nil` as falsy, everything
102
+ As per Ruby, Opal treats only `false` and `nil` as falsy, everything
103
103
  else is a truthy value including `""`, `0` and `[]`. This differs from
104
- javascript as these values are also treated as false.
104
+ JavaScript as these values are also treated as false.
105
105
 
106
106
  For this reason, most truthy tests must check if values are `false` or
107
107
  `nil`.
@@ -133,7 +133,7 @@ This makes the generated truthy tests (`if` statements, `and` checks and
133
133
 
134
134
  Instance variables in Opal work just as expected. When ivars are set or
135
135
  retrieved on an object, they are set natively without the `@` prefix.
136
- This allows real javascript identifiers to be used which is more
136
+ This allows real JavaScript identifiers to be used which is more
137
137
  efficient then accessing variables by string name.
138
138
 
139
139
  ```ruby
@@ -152,13 +152,13 @@ this.foo; // => 200
152
152
  this.bar; // => nil
153
153
  ```
154
154
 
155
- NOTE: If an instance variable uses the same name as a reserved javascript keyword,
155
+ NOTE: If an instance variable uses the same name as a reserved JavaScript keyword,
156
156
  then the instance variable is wrapped using the object-key notation: `this['class']`.
157
157
 
158
158
  ## Compiled Files
159
159
 
160
- As described above, a compiled ruby source gets generated into a string
161
- of javascript code that is wrapped inside an anonymous function. This
160
+ As described above, a compiled Ruby source gets generated into a string
161
+ of JavaScript code that is wrapped inside an anonymous function. This
162
162
  looks similar to the following:
163
163
 
164
164
  ```javascript
@@ -194,14 +194,14 @@ written to the browser's console.
194
194
 
195
195
  ### Debugging and finding errors
196
196
 
197
- Because Opal does not aim to be fully compatible with ruby, there are
197
+ Because Opal does not aim to be fully compatible with Ruby, there are
198
198
  some instances where things can break and it may not be entirely
199
199
  obvious what went wrong.
200
200
 
201
- ### Using javascript debuggers
201
+ ### Using JavaScript debuggers
202
202
 
203
- As opal just generates javascript, it is useful to use a native
204
- debugger to work through javascript code. To use a debugger, simply
203
+ As Opal just generates JavaScript, it is useful to use a native
204
+ debugger to work through JavaScript code. To use a debugger, simply
205
205
  add an x-string similar to the following at the place you wish to
206
206
  debug:
207
207
 
@@ -211,31 +211,32 @@ debug:
211
211
  # .. more code
212
212
  ```
213
213
  The x-strings just pass the debugger statement straight through to the
214
- javascript output.
214
+ JavaScript output.
215
215
 
216
- NOTE: All local variables and method/block arguments also keep their ruby
217
- names except in the rare cases when the name is reserved in javascript.
216
+ NOTE: All local variables and method/block arguments also keep their Ruby
217
+ names except in the rare cases when the name is reserved in JavaScript.
218
218
  In these cases, a `$` suffix is added to the name
219
219
  (e.g. `try` → `try$`).
220
220
 
221
- ## Javascript from Ruby
222
221
 
223
- Opal tries to interact as cleanly with javascript and its api as much
222
+ ## JavaScript from Ruby
223
+
224
+ Opal tries to interact as cleanly with JavaScript and its api as much
224
225
  as possible. Ruby arrays, strings, numbers, regexps, blocks and booleans
225
- are just javascript native equivalents. The only boxed core features are
226
+ are just JavaScript native equivalents. The only boxed core features are
226
227
  hashes.
227
228
 
228
229
 
229
- ### Inline Javascript
230
+ ### Inline JavaScript
230
231
 
231
- As most of the corelib deals with these low level details, opal provides
232
- a special syntax for inlining javascript code. This is done with
233
- x-strings or "backticks", as their ruby use has no useful translation
232
+ As most of the corelib deals with these low level details, Opal provides
233
+ a special syntax for inlining JavaScript code. This is done with
234
+ x-strings or "backticks", as their Ruby use has no useful translation
234
235
  in the browser.
235
236
 
236
237
  ```ruby
237
238
  `window.title`
238
- # => "Opal: Ruby to Javascript compiler"
239
+ # => "Opal: Ruby to JavaScript compiler"
239
240
 
240
241
  %x{
241
242
  console.log("opal version is:");
@@ -267,7 +268,9 @@ as used by this example.
267
268
 
268
269
  _Reposted from: [Mikamayhem](http://dev.mikamai.com/post/79398725537/using-native-javascript-objects-from-opal)_
269
270
 
270
- Opal standard lib (stdlib) includes a `Native` module, let’s see how it works and wrap `window`:
271
+ Opal standard lib (stdlib) includes a `Native` module. To use it, you need to download and reference `native.js`. You can find the latest minified one from the CDN [here](http://cdn.opalrb.org/opal/current/native.min.js).
272
+
273
+ Let's see how it works and wrap `window`:
271
274
 
272
275
  ```ruby
273
276
  require 'native'
@@ -314,34 +317,190 @@ That’s all for now, bye!
314
317
  window.close!
315
318
  ```
316
319
 
317
- ## Ruby from Javascript
320
+ ### Calling JavaScript Methods
321
+
322
+ You can make direct JavaScript method calls on using the `recv.JS.method`
323
+ syntax. For example, if you have a JavaScript object named `foo` and want to call the
324
+ `bar` method on it with no arguments, with or without parentheses:
325
+
326
+ ```ruby
327
+ # javascript: foo.bar()
328
+ foo.JS.bar
329
+ foo.JS.bar()
330
+ ```
331
+
332
+ You can call the JavaScript methods with arguments, with or without parentheses, just
333
+ like Ruby methods:
334
+
335
+ ```ruby
336
+ # JavaScript: foo.bar(1, "a")
337
+ foo.JS.bar(1, :a)
338
+ foo.JS.bar 1, :a
339
+ ```
340
+
341
+ You can call the JavaScript methods with argument splats:
342
+
343
+ ```ruby
344
+ # JavaScript: ($a = foo).bar.apply($a, [1].concat([2, 3]))
345
+ foo.JS.bar(1, *[2, 3])
346
+ foo.JS.bar 1, *[2, 3]
347
+ ```
348
+
349
+ You can provide a block when making a JavaScript method call, and it will be
350
+ converted to a JavaScript function added as the last argument to the method:
351
+
352
+ ```ruby
353
+ # JavaScript:
354
+ # ($a = (TMP_1 = function(arg){
355
+ # var self = TMP_1.$$s || this;
356
+ # if (arg == null) arg = nil;
357
+ # return "" + (arg.method()) + " " + (self.$baz(3))
358
+ # },
359
+ # TMP_1.$$s = self, TMP_1),
360
+ # foo.bar)(1, 2, $a);
361
+ foo.JS.bar(1, 2){|arg| arg.JS.method + baz(3)}
362
+ ```
363
+
364
+ Note how `self` is set for the JavaScript function passed as an argument. This
365
+ allows normal Ruby block behavior to work when passing blocks to JavaScript
366
+ methods.
318
367
 
319
- Accessing classes and methods defined in Opal from the javascript runtime is
368
+ The `.JS.` syntax is recognized as a special token by the lexer, so if you have
369
+ a Ruby method named `JS` that you want to call, you can add a space to call it:
370
+
371
+ ```ruby
372
+ # call Ruby JS method on foo, call Ruby bar method on result
373
+ foo. JS.bar
374
+ ```
375
+
376
+ ### Getting/Setting JavaScript Properties
377
+
378
+ You can get JavaScript properties using the `recv.JS[:property]` syntax:
379
+
380
+ ```ruby
381
+ # JavaScript: foo["bar"]
382
+ foo.JS[:bar]
383
+ ```
384
+
385
+ This also works for JavaScript array access:
386
+
387
+ ```ruby
388
+ # JavaScript: foo[2]
389
+ foo.JS[2]
390
+ ```
391
+
392
+ You can set JavaScript properties using this as the left hand side in an
393
+ assignment:
394
+
395
+ ```ruby
396
+ # JavaScript: foo["bar"] = 1
397
+ foo.JS[:bar] = 1
398
+ ```
399
+
400
+ This also works for setting values in a JavaScript array:
401
+
402
+ ```ruby
403
+ # JavaScript: foo[2] = "a"
404
+ foo.JS[2] = :a
405
+ ```
406
+
407
+ Like the `recv.JS.method` syntax, `.JS[` is recognized as a special token by
408
+ the lexer, so if you want to call the Ruby `JS` method on a object and then
409
+ call the Ruby `[]` method on the result, you can add a space:
410
+
411
+ ```ruby
412
+ # call Ruby JS method on foo, call Ruby [] method on result with :a argument
413
+ foo. JS[:a]
414
+ ```
415
+
416
+ ### Calling JavaScript Operators
417
+
418
+ Opal has a `js` library in the stdlib that provides a `JS` module which can
419
+ be used to call JavaScript operators such as `new`. Example:
420
+
421
+ ```ruby
422
+ require 'js'
423
+
424
+ # new foo(bar)
425
+ JS.new(foo, bar)
426
+
427
+ # delete foo["bar"]
428
+ JS.delete(foo, :bar)
429
+
430
+ # "bar" in foo
431
+ JS.in(:bar, foo)
432
+
433
+ # foo instanceof bar
434
+ JS.instanceof(foo, bar)
435
+
436
+ # typeof foo
437
+ JS.typeof(foo)
438
+ ```
439
+
440
+ ### Calling JavaScript Global Functions
441
+
442
+ You can also use the `js` library to call JavaScript global functions via
443
+ `JS.call`:
444
+
445
+ ```ruby
446
+ require 'js'
447
+
448
+ # parseFloat("1.1")
449
+ JS.call(:parseFloat, "1.1")
450
+ ```
451
+
452
+ For convenience, `method_missing` is aliased to call, allowing you to call
453
+ global JavaScript methods directly on the `JS` module:
454
+
455
+ ```ruby
456
+ require 'js'
457
+
458
+ # parseFloat("1.1")
459
+ JS.parseFloat("1.1")
460
+ ```
461
+
462
+
463
+ ### Wrapping JavaScript Libraries
464
+
465
+ If you want to integrate a JavaScript library with Opal, so that you can make Ruby calls, you can choose one of the following options:
466
+
467
+ - **Use backticks:** This is the quickest, simplest approach to integrating: call the native JavaScript code directly; it may provide a slight performance benefit, but also produces "ugly" Ruby code riddled with JavaScript. It's ideal for occasional calls to a JavaScript library.
468
+
469
+ - **Use `.JS`:** You can make direct JavaScript method calls on using the `recv.JS.method` syntax. It is very similar to using backticks but looks more like ruby.
470
+
471
+ - **Use `Native`:** `Native` provides a reasonable Ruby-like wrapper around JavaScript objects. This provides a quick in-term solution if no dedicated Ruby wrapper library exists.
472
+
473
+ - **Create your own Wrapper Library:** If you use the library a lot, you can create your own Ruby library that wraps the JavaScript calls (which call `Native` or use backticks under the hood). This provides the best abstraction (eg. you can provide high-level calls that provide functionality, regardless of if the underlying JavaScript call flows change).
474
+
475
+
476
+ ## Ruby from JavaScript
477
+
478
+ Accessing classes and methods defined in Opal from the JavaScript runtime is
320
479
  possible via the `Opal` js object. The following class:
321
480
 
322
481
  ```ruby
323
482
  class Foo
324
483
  def bar
325
- puts "called bar on class Foo defined in ruby code"
484
+ puts "called bar on class Foo defined in Ruby code"
326
485
  end
327
486
  end
328
487
  ```
329
488
 
330
- Can be accessed from javascript like this:
489
+ Can be accessed from JavaScript like this:
331
490
 
332
491
  ```javascript
333
492
  Opal.Foo.$new().$bar();
334
- // => "called bar on class Foo defined in ruby code"
493
+ // => "called bar on class Foo defined in Ruby code"
335
494
  ```
336
495
 
337
- Remember that all ruby methods are prefixed with a `$`.
496
+ Remember that all Ruby methods are prefixed with a `$`.
338
497
 
339
- In the case that a method name can't be called directly due to a javascript syntax error, you will need to call the method using bracket notation. For example, you can call `foo.$merge(...)` but not `foo.$merge!(...)`, `bar.$fetch('somekey')` but not `bar.$[]('somekey')`. Instead you would write it like this: `foo['$merge!'](...)` or `bar['$[]']('somekey')`.
498
+ In the case that a method name can't be called directly due to a JavaScript syntax error, you will need to call the method using bracket notation. For example, you can call `foo.$merge(...)` but not `foo.$merge!(...)`, `bar.$fetch('somekey')` but not `bar.$[]('somekey')`. Instead you would write it like this: `foo['$merge!'](...)` or `bar['$[]']('somekey')`.
340
499
 
341
500
 
342
501
  ### Hash
343
502
 
344
- Since ruby hashes are implemented directly with an Opal class, there's no "toll-free" bridging available (unlike with strings and arrays, for example). However, it's quite possible to interact with hashes from Javascript:
503
+ Since Ruby hashes are implemented directly with an Opal class, there's no "toll-free" bridging available (unlike with strings and arrays, for example). However, it's quite possible to interact with hashes from JavaScript:
345
504
 
346
505
  ```javascript
347
506
  var myHash = Opal.hash({a: 1, b: 2});
@@ -355,7 +514,7 @@ myHash.$fetch('z','');
355
514
  myHash.$update(Opal.hash({b: 20, c: 30}));
356
515
  // output of $inspect: {"a"=>10, "b"=>20, "c"=>30}
357
516
  myHash.$to_n(); // provided by the Native module
358
- // output: {"a": 10, "b": 20, "c": 30} aka a standard Javascript object
517
+ // output: {"a": 10, "b": 20, "c": 30} aka a standard JavaScript object
359
518
  ```
360
519
 
361
520
  NOTE: Be aware `Hash#to_n` produces a duplicate copy of the hash.
@@ -364,32 +523,32 @@ NOTE: Be aware `Hash#to_n` produces a duplicate copy of the hash.
364
523
 
365
524
  ### Method Missing
366
525
 
367
- Opal supports `method_missing`. This is a key feature of ruby, and opal wouldn't be much use without it! This page details the implementation of `method_missing` for Opal.
526
+ Opal supports `method_missing`. This is a key feature of Ruby, and Opal wouldn't be much use without it! This page details the implementation of `method_missing` for Opal.
368
527
 
369
528
  #### Method dispatches
370
529
 
371
- Firstly, a ruby call `foo.bar 1, 2, 3` is compiled into the following javascript:
530
+ Firstly, a Ruby call `foo.bar 1, 2, 3` is compiled into the following JavaScript:
372
531
 
373
532
  ```javascript
374
533
  foo.$bar(1, 2, 3)
375
534
  ```
376
535
 
377
- This should be pretty easy to read. The `bar` method has a `$` prefix just to distinguish it from underlying javascript properties, as well as ruby ivars. Methods are compiled like this to make the generated code really readable.
536
+ This should be pretty easy to read. The `bar` method has a `$` prefix just to distinguish it from underlying JavaScript properties, as well as Ruby ivars. Methods are compiled like this to make the generated code really readable.
378
537
 
379
538
  #### Handling `method_missing`
380
539
 
381
- Javascript does not have an equivalent of `method_missing`, so how do we handle it? If a function is missing in javascript, then a language level exception will be raised.
540
+ JavaScript does not have an equivalent of `method_missing`, so how do we handle it? If a function is missing in JavaScript, then a language level exception will be raised.
382
541
 
383
- To get around this, we make use of our compiler. During parsing, we collect a list of all method calls made inside a ruby file, and this gives us a list of all possible method calls. We then add stub methods to the root object prototype (an opal object, not the global javascript Object) which will proxy our method missing calls for us.
542
+ To get around this, we make use of our compiler. During parsing, we collect a list of all method calls made inside a Ruby file, and this gives us a list of all possible method calls. We then add stub methods to the root object prototype (an Opal object, not the global JavaScript Object) which will proxy our method missing calls for us.
384
543
 
385
- For example, assume the following ruby script:
544
+ For example, assume the following Ruby script:
386
545
 
387
546
  ```ruby
388
547
  first 1, 2, 3
389
548
  second "wow".to_sym
390
549
  ```
391
550
 
392
- After parsing, we know we only ever call 3 methods: `[:first, :second, :to_sym]`. So, imagine we could just add these 3 methods to `BasicObject` in ruby, we would get something like this:
551
+ After parsing, we know we only ever call 3 methods: `[:first, :second, :to_sym]`. So, imagine we could just add these 3 methods to `BasicObject` in Ruby, we would get something like this:
393
552
 
394
553
  ```ruby
395
554
  class BasicObject
@@ -407,19 +566,18 @@ class BasicObject
407
566
  end
408
567
  ```
409
568
 
410
- It is obvious from here, that unless an object defines any given method, it will always resort in a dispatch to `method_missing` from one of our defined stub methods. This is how we get `method_missing` in opal.
569
+ It is obvious from here, that unless an object defines any given method, it will always resort in a dispatch to `method_missing` from one of our defined stub methods. This is how we get `method_missing` in Opal.
411
570
 
412
571
  #### Optimising generated code
413
572
 
414
- To optimise the generated code slightly, we reduce the code output from the compiler into the following javascript:
573
+ To optimise the generated code slightly, we reduce the code output from the compiler into the following JavaScript:
415
574
 
416
575
  ```javascript
417
576
  Opal.add_stubs(["first", "second", "to_sym"]);
418
577
  ```
419
578
 
420
- You will see this at the top of all your generated javascript files. This will add a stub method for all methods used in your file.
579
+ You will see this at the top of all your generated JavaScript files. This will add a stub method for all methods used in your file.
421
580
 
422
581
  #### Alternative approaches
423
582
 
424
583
  The old approach was to inline `method_missing` calls by checking for a method on **every method dispatch**. This is still supported via a parser option, but not recommended.
425
-