opal 0.5.5 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (257) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +40 -9
  3. data/CHANGELOG.md +349 -0
  4. data/Gemfile +7 -8
  5. data/README.md +25 -3
  6. data/Rakefile +4 -2
  7. data/bin/opal +1 -1
  8. data/examples/rack/Gemfile +3 -0
  9. data/examples/rack/app/application.rb +13 -0
  10. data/examples/rack/app/user.rb +21 -0
  11. data/examples/rack/config.ru +7 -0
  12. data/examples/rack/index.html.erb +10 -0
  13. data/examples/sinatra/Gemfile +4 -0
  14. data/examples/sinatra/app/application.rb +7 -0
  15. data/examples/sinatra/config.ru +21 -0
  16. data/lib/mspec/opal/rake_task.rb +29 -8
  17. data/lib/mspec/opal/runner.rb +5 -4
  18. data/lib/opal.rb +1 -0
  19. data/lib/opal/builder.rb +0 -28
  20. data/lib/opal/cli.rb +0 -14
  21. data/lib/opal/compiler.rb +12 -11
  22. data/lib/opal/fragment.rb +8 -1
  23. data/lib/opal/nodes/array.rb +1 -1
  24. data/lib/opal/nodes/base.rb +4 -0
  25. data/lib/opal/nodes/call.rb +6 -2
  26. data/lib/opal/nodes/call_special.rb +1 -1
  27. data/lib/opal/nodes/class.rb +2 -2
  28. data/lib/opal/nodes/constants.rb +3 -1
  29. data/lib/opal/nodes/helpers.rb +23 -14
  30. data/lib/opal/nodes/if.rb +16 -9
  31. data/lib/opal/nodes/literal.rb +37 -5
  32. data/lib/opal/nodes/logic.rb +7 -1
  33. data/lib/opal/nodes/module.rb +2 -2
  34. data/lib/opal/nodes/scope.rb +13 -2
  35. data/lib/opal/nodes/top.rb +9 -0
  36. data/lib/opal/nodes/variables.rb +5 -2
  37. data/lib/opal/parser.rb +306 -71
  38. data/lib/opal/parser/grammar.rb +2667 -2775
  39. data/lib/opal/parser/grammar.y +177 -233
  40. data/lib/opal/parser/lexer.rb +511 -427
  41. data/lib/opal/parser/sexp.rb +15 -3
  42. data/lib/opal/source_map.rb +8 -4
  43. data/lib/opal/sprockets.rb +4 -0
  44. data/lib/opal/sprockets/cache_key_fix.rb +17 -0
  45. data/lib/opal/sprockets/environment.rb +21 -0
  46. data/lib/opal/sprockets/erb.rb +30 -0
  47. data/lib/opal/sprockets/processor.rb +127 -0
  48. data/lib/opal/sprockets/server.rb +166 -0
  49. data/lib/opal/util.rb +29 -0
  50. data/lib/opal/version.rb +1 -1
  51. data/opal.gemspec +1 -1
  52. data/opal/corelib/array.rb +106 -187
  53. data/opal/corelib/array/inheritance.rb +113 -0
  54. data/opal/corelib/basic_object.rb +6 -2
  55. data/opal/corelib/boolean.rb +4 -0
  56. data/opal/corelib/class.rb +2 -0
  57. data/opal/corelib/complex.rb +3 -0
  58. data/opal/corelib/enumerable.rb +75 -8
  59. data/opal/corelib/enumerator.rb +2 -0
  60. data/opal/corelib/error.rb +23 -23
  61. data/opal/corelib/hash.rb +5 -5
  62. data/opal/corelib/helpers.rb +51 -16
  63. data/opal/corelib/io.rb +7 -24
  64. data/opal/corelib/kernel.rb +23 -11
  65. data/opal/corelib/module.rb +44 -47
  66. data/opal/corelib/nil_class.rb +4 -0
  67. data/opal/corelib/numeric.rb +101 -15
  68. data/opal/corelib/range.rb +2 -0
  69. data/opal/corelib/rational.rb +3 -0
  70. data/opal/corelib/regexp.rb +36 -17
  71. data/opal/corelib/runtime.js +22 -7
  72. data/opal/corelib/string.rb +213 -110
  73. data/opal/corelib/string/inheritance.rb +78 -0
  74. data/opal/corelib/struct.rb +8 -0
  75. data/opal/corelib/time.rb +54 -42
  76. data/opal/corelib/variables.rb +24 -0
  77. data/opal/opal.rb +5 -27
  78. data/spec/cli/compiler_spec.rb +136 -0
  79. data/spec/cli/dependency_resolver_spec.rb +40 -0
  80. data/spec/cli/lexer_spec.rb +110 -0
  81. data/spec/cli/parser/alias_spec.rb +26 -0
  82. data/spec/cli/parser/and_spec.rb +13 -0
  83. data/spec/cli/parser/attrasgn_spec.rb +28 -0
  84. data/spec/cli/parser/begin_spec.rb +42 -0
  85. data/spec/cli/parser/block_spec.rb +12 -0
  86. data/spec/cli/parser/break_spec.rb +17 -0
  87. data/spec/cli/parser/call_spec.rb +139 -0
  88. data/spec/cli/parser/class_spec.rb +35 -0
  89. data/spec/cli/parser/comments_spec.rb +11 -0
  90. data/spec/cli/parser/def_spec.rb +61 -0
  91. data/spec/cli/parser/if_spec.rb +26 -0
  92. data/spec/cli/parser/iter_spec.rb +59 -0
  93. data/spec/cli/parser/lambda_spec.rb +64 -0
  94. data/spec/cli/parser/literal_spec.rb +113 -0
  95. data/spec/cli/parser/masgn_spec.rb +37 -0
  96. data/spec/cli/parser/module_spec.rb +27 -0
  97. data/spec/cli/parser/not_spec.rb +27 -0
  98. data/spec/cli/parser/op_asgn1_spec.rb +23 -0
  99. data/spec/cli/parser/op_asgn2_spec.rb +23 -0
  100. data/spec/cli/parser/or_spec.rb +13 -0
  101. data/spec/cli/parser/return_spec.rb +17 -0
  102. data/spec/cli/parser/sclass_spec.rb +21 -0
  103. data/spec/cli/parser/string_spec.rb +269 -0
  104. data/spec/cli/parser/super_spec.rb +20 -0
  105. data/spec/cli/parser/undef_spec.rb +15 -0
  106. data/spec/cli/parser/unless_spec.rb +13 -0
  107. data/spec/cli/parser/variables_spec.rb +92 -0
  108. data/spec/cli/parser/while_spec.rb +15 -0
  109. data/spec/cli/parser/yield_spec.rb +20 -0
  110. data/spec/cli/spec_helper.rb +31 -11
  111. data/spec/opal/core/array/set_range_to_array_spec.rb +7 -0
  112. data/spec/opal/core/date_spec.rb +122 -0
  113. data/spec/opal/core/language/predefined_spec.rb +1 -1
  114. data/spec/opal/core/runtime/operator_call_spec.rb +13 -0
  115. data/spec/opal/core/runtime/truthy_spec.rb +23 -0
  116. data/spec/opal/filters/bugs/array.rb +96 -87
  117. data/spec/opal/filters/bugs/basic_object.rb +9 -0
  118. data/spec/opal/filters/bugs/class.rb +16 -0
  119. data/spec/opal/filters/bugs/enumerable.rb +54 -0
  120. data/spec/opal/filters/bugs/language.rb +37 -3
  121. data/spec/opal/filters/bugs/math.rb +93 -0
  122. data/spec/opal/filters/bugs/nil.rb +7 -0
  123. data/spec/opal/filters/bugs/numeric.rb +19 -0
  124. data/spec/opal/filters/bugs/opal.rb +12 -0
  125. data/spec/opal/filters/bugs/regexp.rb +0 -2
  126. data/spec/opal/filters/bugs/string.rb +317 -19
  127. data/spec/opal/filters/bugs/struct.rb +29 -0
  128. data/spec/opal/filters/bugs/time.rb +130 -9
  129. data/spec/opal/filters/unsupported/encoding.rb +52 -4
  130. data/spec/opal/filters/unsupported/enumerator.rb +0 -3
  131. data/spec/opal/filters/unsupported/integer_size.rb +7 -0
  132. data/spec/opal/filters/unsupported/method_added.rb +10 -0
  133. data/spec/opal/filters/unsupported/mutable_strings.rb +299 -1
  134. data/spec/opal/filters/unsupported/private_constants.rb +30 -0
  135. data/spec/opal/filters/unsupported/private_methods.rb +16 -0
  136. data/spec/opal/filters/unsupported/random.rb +4 -0
  137. data/spec/opal/filters/unsupported/tainted.rb +53 -0
  138. data/spec/opal/filters/unsupported/trusted.rb +5 -0
  139. data/spec/opal/rubyspecs +167 -234
  140. data/spec/opal/spec_helper.rb +3 -0
  141. data/spec/opal/stdlib/promise/error_spec.rb +15 -0
  142. data/spec/opal/stdlib/promise/rescue_spec.rb +35 -0
  143. data/spec/opal/stdlib/promise/then_spec.rb +54 -0
  144. data/spec/opal/stdlib/promise/trace_spec.rb +35 -0
  145. data/spec/opal/stdlib/promise/value_spec.rb +15 -0
  146. data/spec/opal/stdlib/promise/when_spec.rb +34 -0
  147. data/stdlib/base64.rb +152 -0
  148. data/stdlib/date.rb +82 -49
  149. data/{opal/corelib → stdlib}/encoding.rb +3 -1
  150. data/stdlib/erb.rb +0 -1
  151. data/stdlib/json.rb +10 -26
  152. data/stdlib/math.rb +370 -0
  153. data/stdlib/native.rb +40 -33
  154. data/stdlib/opal-parser.rb +7 -4
  155. data/stdlib/promise.rb +292 -0
  156. data/stdlib/strscan.rb +1 -1
  157. data/stdlib/template.rb +1 -3
  158. data/stdlib/time.rb +9 -0
  159. metadata +143 -204
  160. data/doc/compiler.md +0 -42
  161. data/doc/compiler_options.md +0 -5
  162. data/doc/examples/node_http_server.rb +0 -49
  163. data/doc/external_libraries.md +0 -9
  164. data/doc/generated_javascript.md +0 -272
  165. data/doc/home.md +0 -17
  166. data/doc/method_missing.md +0 -58
  167. data/doc/static_applications.md +0 -60
  168. data/doc/using_ruby_from_javascript.md +0 -18
  169. data/doc/using_sprockets.md +0 -65
  170. data/spec/opal/core/numeric/abs_spec.rb +0 -12
  171. data/spec/opal/core/numeric/downto_spec.rb +0 -19
  172. data/spec/opal/core/numeric/equal_value_spec.rb +0 -9
  173. data/spec/opal/core/numeric/even_spec.rb +0 -21
  174. data/spec/opal/core/numeric/magnitude_spec.rb +0 -12
  175. data/spec/opal/core/numeric/odd_spec.rb +0 -21
  176. data/spec/opal/core/string/chop_spec.rb +0 -10
  177. data/spec/opal/core/string/chr_spec.rb +0 -13
  178. data/spec/opal/core/string/clone_spec.rb +0 -8
  179. data/spec/opal/core/string/comparison_spec.rb +0 -13
  180. data/spec/opal/core/string/dup_spec.rb +0 -8
  181. data/spec/opal/core/string/element_reference_spec.rb +0 -96
  182. data/spec/opal/core/string/fixtures/classes.rb +0 -49
  183. data/spec/opal/core/string/format_spec.rb +0 -9
  184. data/spec/opal/core/string/freeze_spec.rb +0 -15
  185. data/spec/opal/core/string/gsub_spec.rb +0 -31
  186. data/spec/opal/core/string/lines_spec.rb +0 -9
  187. data/spec/opal/core/string/ljust_spec.rb +0 -32
  188. data/spec/opal/core/string/lstrip_spec.rb +0 -7
  189. data/spec/opal/core/string/match_spec.rb +0 -49
  190. data/spec/opal/core/string/next_spec.rb +0 -10
  191. data/spec/opal/core/string/ord_spec.rb +0 -9
  192. data/spec/opal/core/string/partition_spec.rb +0 -10
  193. data/spec/opal/core/string/rindex_spec.rb +0 -50
  194. data/spec/opal/core/string/rjust_spec.rb +0 -32
  195. data/spec/opal/core/string/rstrip_spec.rb +0 -7
  196. data/spec/opal/core/string/scan_spec.rb +0 -66
  197. data/spec/opal/core/string/slice_spec.rb +0 -74
  198. data/spec/opal/core/string/split_spec.rb +0 -5
  199. data/spec/opal/core/string/strip_spec.rb +0 -6
  200. data/spec/opal/core/string/sub_spec.rb +0 -38
  201. data/spec/opal/core/string/succ_spec.rb +0 -10
  202. data/spec/opal/core/string/sum_spec.rb +0 -5
  203. data/spec/opal/core/string/to_f_spec.rb +0 -14
  204. data/spec/opal/core/string/to_i_spec.rb +0 -25
  205. data/spec/opal/core/string/tr_s_spec.rb +0 -31
  206. data/spec/opal/core/string/tr_spec.rb +0 -31
  207. data/spec/opal/filters/bugs/parser.rb +0 -10
  208. data/spec/opal/filters/unsupported/immutable_strings.rb +0 -24
  209. data/spec/opal/filters/unsupported/string_subclasses.rb +0 -8
  210. data/spec/opal/parser/alias_spec.rb +0 -26
  211. data/spec/opal/parser/and_spec.rb +0 -13
  212. data/spec/opal/parser/array_spec.rb +0 -22
  213. data/spec/opal/parser/attrasgn_spec.rb +0 -28
  214. data/spec/opal/parser/begin_spec.rb +0 -42
  215. data/spec/opal/parser/block_spec.rb +0 -12
  216. data/spec/opal/parser/break_spec.rb +0 -17
  217. data/spec/opal/parser/call_spec.rb +0 -131
  218. data/spec/opal/parser/class_spec.rb +0 -35
  219. data/spec/opal/parser/const_spec.rb +0 -13
  220. data/spec/opal/parser/cvar_spec.rb +0 -11
  221. data/spec/opal/parser/def_spec.rb +0 -61
  222. data/spec/opal/parser/false_spec.rb +0 -17
  223. data/spec/opal/parser/file_spec.rb +0 -7
  224. data/spec/opal/parser/gvar_spec.rb +0 -13
  225. data/spec/opal/parser/hash_spec.rb +0 -17
  226. data/spec/opal/parser/heredoc_spec.rb +0 -30
  227. data/spec/opal/parser/iasgn_spec.rb +0 -9
  228. data/spec/opal/parser/if_spec.rb +0 -26
  229. data/spec/opal/parser/int_spec.rb +0 -13
  230. data/spec/opal/parser/iter_spec.rb +0 -59
  231. data/spec/opal/parser/ivar_spec.rb +0 -9
  232. data/spec/opal/parser/lambda_spec.rb +0 -64
  233. data/spec/opal/parser/lasgn_spec.rb +0 -8
  234. data/spec/opal/parser/line_spec.rb +0 -8
  235. data/spec/opal/parser/lvar_spec.rb +0 -38
  236. data/spec/opal/parser/masgn_spec.rb +0 -37
  237. data/spec/opal/parser/module_spec.rb +0 -27
  238. data/spec/opal/parser/nil_spec.rb +0 -17
  239. data/spec/opal/parser/not_spec.rb +0 -27
  240. data/spec/opal/parser/nth_ref_spec.rb +0 -13
  241. data/spec/opal/parser/op_asgn1_spec.rb +0 -23
  242. data/spec/opal/parser/op_asgn2_spec.rb +0 -23
  243. data/spec/opal/parser/or_spec.rb +0 -13
  244. data/spec/opal/parser/parse_spec.rb +0 -66
  245. data/spec/opal/parser/regexp_spec.rb +0 -16
  246. data/spec/opal/parser/return_spec.rb +0 -17
  247. data/spec/opal/parser/sclass_spec.rb +0 -21
  248. data/spec/opal/parser/self_spec.rb +0 -17
  249. data/spec/opal/parser/str_spec.rb +0 -107
  250. data/spec/opal/parser/string_spec.rb +0 -8
  251. data/spec/opal/parser/super_spec.rb +0 -20
  252. data/spec/opal/parser/true_spec.rb +0 -17
  253. data/spec/opal/parser/undef_spec.rb +0 -15
  254. data/spec/opal/parser/unless_spec.rb +0 -13
  255. data/spec/opal/parser/while_spec.rb +0 -15
  256. data/spec/opal/parser/xstr_spec.rb +0 -116
  257. data/spec/opal/parser/yield_spec.rb +0 -20
@@ -1,42 +0,0 @@
1
- # Opal Compiler
2
-
3
- Opal is a source to source compiler. It accepts ruby code as a string and
4
- generates javascript code which can be run in any environment. Generated
5
- code relies on the opal runtime which provides the class system and some
6
- other runtime helpers.
7
-
8
- ## Compiler stages
9
-
10
- The compiler can be broken down into 3 separate stages:
11
-
12
- * lexing
13
- * parsing
14
- * code generation
15
-
16
- ### Lexer
17
-
18
- The [opal lexer](../lib/opal/parser/lexer.rb) is implemented in pure ruby using
19
- the `StringScanner` class from the opal stdlib. The source code is scanned
20
- and tokens are then provided to the parser. This process simply converts
21
- the ruby code given as a string, into a list of tokens representing the
22
- parts of the ruby code.
23
-
24
- ### Parser
25
-
26
- The [opal parser](../lib/opal/parser/grammar.y) is implemented using a standard
27
- bison like syntax, but relies on `racc`, a ruby implementation of yacc/bison
28
- which is again available in the standard library. The parser takes these tokens
29
- generated by the lexer and builds a syntax tree representing the ruby code.
30
- This syntax tree is represented by [sexps](../lib/opal/parser/sexp.rb). As
31
- ruby is such a complex and dynamic language, there is a lot of interaction
32
- between the parser and the lexer, namely through a preserved `lex_state`.
33
-
34
- ### Code generation
35
-
36
- The [opal compiler](../lib/opal/compiler.rb) takes these sexps from the parser
37
- and generates ruby code from them. Each type of sexp has [its own node type](../lib/opal/nodes/base.rb)
38
- used to generate javascript. Each node creates an array of one or more
39
- [fragments](../lib/opal/fragment.rb) which are the concatendated together to
40
- form the final javascript. Fragments are used as they contain the generated
41
- code as well as a reference back to the original sexp which is useful for
42
- generating source maps afterwards.
@@ -1,5 +0,0 @@
1
- ## General options to be used inside source files
2
-
3
- * method_missing
4
- * const_missing
5
- * optimized operators for Number
@@ -1,49 +0,0 @@
1
- # run with:
2
- #
3
- # bundle exec ./bin/opal ./doc/examples/node_http_server.rb
4
- #
5
-
6
- %x{
7
- var http;
8
- http = require('http');
9
- }
10
-
11
-
12
- module HTTP
13
- class Server
14
- %x{
15
- var dom_class = http.Server;
16
- #{self}['_proto'] = dom_class.prototype;
17
- def = #{self}._proto;
18
- dom_class.prototype._klass = #{self};
19
- }
20
-
21
- def self.__http__
22
- Native(`http`)
23
- end
24
-
25
- alias_native :listen, :listen
26
-
27
- def self.start options = {}, &block
28
- host = options[:host] || '127.0.0.1'
29
- port = options[:port] || 3000
30
-
31
- server = __http__.createServer do |req, res|
32
- req = Native(req)
33
- res = Native(res)
34
- status, headers, body = block.call(`req`)
35
- res.writeHead(status, headers.to_n);
36
- res.end(body.join(' '));
37
- end
38
-
39
- server.listen(port, host)
40
- puts("Server running at http://#{host}:#{port}/");
41
- server
42
- end
43
- end
44
- end
45
-
46
- util = Native(`require('util')`)
47
- HTTP::Server.start port: 3000 do |env|
48
- [200, {'Content-Type' => 'text/plain'}, ["Hello World!\n", util.inspect(env)]]
49
- end
@@ -1,9 +0,0 @@
1
- # Using external libraries in your opal app
2
-
3
- ## with Opal::Builder
4
-
5
- _WIP_
6
-
7
- ## With opal-sprockets
8
-
9
- _WIP_
@@ -1,272 +0,0 @@
1
- # Generated Javascript
2
-
3
- Opal is a source-to-source compiler, so there is no VM as such and the
4
- compiled code aims to be as fast and efficient as possible, mapping
5
- directly to underlying javascript features and objects where possible.
6
-
7
- ## Overview
8
-
9
- ruby | javascript
10
- -------------------------|---------------------------
11
- `self` | `this`
12
- `true` | `true`
13
- `false` | `false`
14
- `nil` | `nil`
15
- `42` | `42`
16
- `3.142` | `3.142`
17
- `"hello"` | `"hello"`
18
- `:world` | `"world"`
19
- `[1, 2, 3]` | `[1, 2, 3]`
20
- `{ "a" => 2, "b" => 4 }` | `$opal.hash("a", 2, "b", 4)`
21
- `1..10` | `$opal.range(1, 10)`
22
- `recv.foo` | `recv.$foo()`
23
- `recv.bar(1, 2, 3)` | `recv.$bar(1, 2, 3)`
24
- `recv.baz = 10` | `recv['$baz='](10)`
25
- `a + b` | `a['$+'](b)`
26
-
27
- ## Literals
28
-
29
- **self** is mostly compiled to `this`. Methods and blocks are implemented
30
- as javascript functions, so their `this` value will be the right
31
- `self` value. Class bodies and the top level scope use a `self` variable
32
- to improve readability.
33
-
34
- **true** and **false** are compiled directly into their native boolean
35
- equivalents. This makes interaction a lot easier as there is no need
36
- to convert values to opal specific values. It does mean that there is
37
- only a `Boolean` ruby class available, not seperate `TrueClass` and
38
- `FalseClass` classes.
39
-
40
- **nil** is compiled to a `nil` javascript variable. `nil` is a real object
41
- which allows methods to be called on it. Opal cannot send methods to `null`
42
- or `undefined`, and they are considered bad values to be inside ruby code.
43
-
44
- ```ruby
45
- nil # => nil
46
- true # => true
47
- false # => false
48
- self # => self
49
- ```
50
-
51
- ##### Strings
52
-
53
- Ruby strings are compiled directly into javascript strings for
54
- performance as well as readability. This has the side effect that Opal
55
- does not support mutable strings - i.e. all strings are immutable.
56
-
57
- ##### Symbols
58
-
59
- For performance reasons, symbols compile directly into strings. Opal
60
- supports all the symbol syntaxes, but does not have a real `Symbol`
61
- class. Symbols and Strings can therefore be used interchangeably.
62
-
63
- ```ruby
64
- "hello world!" # => "hello world!"
65
- :foo # => "foo"
66
- <<-EOS # => "\nHello there.\n"
67
- Hello there.
68
- EOS
69
- ```
70
-
71
- ##### Numbers
72
-
73
- In Opal there is a single class for numbers; `Numeric`. To keep opal
74
- as performant as possible, ruby numbers are mapped to native numbers.
75
- This has the side effect that all numbers must be of the same class.
76
- Most relevant methods from `Integer`, `Float` and `Numeric` are
77
- implemented on this class.
78
-
79
- ```ruby
80
- 42 # => 42
81
- 3.142 # => 3.142
82
- ```
83
-
84
- ##### Arrays
85
-
86
- Ruby arrays are compiled directly into javascript arrays. Special
87
- ruby syntaxes for word arrays etc are also supported.
88
-
89
- ```ruby
90
- [1, 2, 3, 4] # => [1, 2, 3, 4]
91
- %w[foo bar baz] # => ["foo", "bar", "baz"]
92
- ```
93
-
94
- ##### Hash
95
-
96
- Inside a generated ruby script, a function `__hash` is available which
97
- creates a new hash. This is also available in javascript as `Opal.hash`
98
- and simply returns a new instance of the `Hash` class.
99
-
100
- ```ruby
101
- { :foo => 100, :baz => 700 } # => __hash("foo", 100, "baz", 700)
102
- { foo: 42, bar: [1, 2, 3] } # => __hash("foo", 42, "bar", [1, 2, 3])
103
- ```
104
-
105
- ##### Range
106
-
107
- Similar to hash, there is a function `__range` available to create
108
- range instances.
109
-
110
- ```ruby
111
- 1..4 # => __range(1, 4, true)
112
- 3...7 # => __range(3, 7, false)
113
- ```
114
-
115
- ## Logic and conditionals
116
-
117
- As per ruby, Opal treats only `false` and `nil` as falsy, everything
118
- else is a truthy value including `""`, `0` and `[]`. This differs from
119
- javascript as these values are also treated as false.
120
-
121
- For this reason, most truthy tests must check if values are `false` or
122
- `nil`.
123
-
124
- Taking the following test:
125
-
126
- ```ruby
127
- val = 42
128
-
129
- if val
130
- return 3.142;
131
- end
132
- ```
133
-
134
- This would be compiled into:
135
-
136
- ```javascript
137
- var val = 42;
138
-
139
- if (val !== false && val !== nil) {
140
- return 3.142;
141
- }
142
- ```
143
-
144
- This makes the generated truthy tests (`if` statements, `and` checks and
145
- `or` statements) a litle more verbose in the generated code.
146
-
147
- ## Instance variables
148
-
149
- Instance variables in Opal work just as expected. When ivars are set or
150
- retrieved on an object, they are set natively without the `@` prefix.
151
- This allows real javascript identifiers to be used which is more
152
- efficient then accessing variables by string name.
153
-
154
- ```ruby
155
- @foo = 200
156
- @foo # => 200
157
-
158
- @bar # => nil
159
- ```
160
-
161
- This gets compiled into:
162
-
163
- ```javascript
164
- this.foo = 200;
165
- this.foo; // => 200
166
-
167
- this.bar; // => nil
168
- ```
169
-
170
- ## Interacting with javascript
171
-
172
- Opal tries to interact as cleanly with javascript and its api as much
173
- as possible. Ruby arrays, strings, numbers, regexps, blocks and booleans
174
- are just javascript native equivalents. The only boxed core features are
175
- hashes.
176
-
177
- As most of the corelib deals with these low level details, opal provides
178
- a special syntax for inlining javascript code. This is done with
179
- x-strings or "backticks", as their ruby use has no useful translation
180
- in the browser.
181
-
182
- ```ruby
183
- `window.title`
184
- # => "Opal: ruby to javascript compiler"
185
-
186
- %x{
187
- console.log("ruby version is:");
188
- console.log(#{ OPAL_VERSION });
189
- }
190
-
191
- # => ruby version is:
192
- # => 0.3.19
193
- ```
194
-
195
- Even interpolations are supported, as seen here.
196
-
197
- This feature of inlining code is used extensively, for example in
198
- Array#length:
199
-
200
- ```ruby
201
- class Array
202
- def length
203
- `this.length`
204
- end
205
- end
206
- ```
207
-
208
- X-Strings also have the ability to automatically return their value,
209
- as used by this example.
210
-
211
- ## Compiled Files
212
-
213
- As described above, a compiled ruby source gets generated into a string
214
- of javascript code that is wrapped inside an anonymous function. This
215
- looks similar to the following:
216
-
217
- ```javascript
218
- (function($opal) {
219
- var $klass = $opal.klass, self = $opal.top;
220
- // generated code
221
- })(Opal);
222
- ```
223
-
224
- As a complete example, assuming the following code:
225
-
226
- ```ruby
227
- puts "foo"
228
- ```
229
-
230
- This would compile directly into:
231
-
232
- ```javascript
233
- (function($opal) {
234
- var $klass = $opal.klass, self = $opal.top;
235
- self.$puts("foo");
236
- })(Opal);
237
- ```
238
-
239
- Most of the helpers are no longer present as they are not used in this
240
- example.
241
-
242
- ## Using compiled sources
243
-
244
- If you write the generated code as above into a file `app.js` and add
245
- that to your HTML page, then it is obvious that `"foo"` would be
246
- written to the browser's console.
247
-
248
- ## Debugging and finding errors
249
-
250
- Because Opal does not aim to be fully compatible with ruby, there are
251
- some instances where things can break and it may not be entirely
252
- obvious what went wrong.
253
-
254
- ### Using javascript debuggers
255
-
256
- As opal just generates javascript, it is useful to use a native
257
- debugger to work through javascript code. To use a debugger, simply
258
- add an x-string similar to the following at the place you wish to
259
- debug:
260
-
261
- ```ruby
262
- # .. code
263
- `debugger`
264
- # .. more code
265
- ```
266
- The x-strings just pass the debugger statement straight through to the
267
- javascript output.
268
-
269
- All local variables and method/block arguments also keep their ruby
270
- names except in the rare cases when the name is reserved in javascript.
271
- In these cases, a `$` suffix is added to the name (e.g. `try` =>
272
- `try$`).
@@ -1,17 +0,0 @@
1
- # Opal
2
-
3
- [Generated Javascript](generated_javascript.md) An overview of the compiler output
4
-
5
- [Method Missing](method_missing.md) How Opal implements method_missing
6
-
7
- [Using Ruby from Javascript](using_ruby_from_javascript.md) How to access ruby methods from JS
8
-
9
- ## Usage
10
-
11
- [Static Application](static_applications.md) Just build your app and dependencies to a build.js file
12
-
13
- [Using Sprockets](using_sprockets.md) Use rack/sprockets to auto-recompile an opal application
14
-
15
- ## Compiler
16
-
17
- [Opal Compiler](compiler.md) An overview of how the compiler works
@@ -1,58 +0,0 @@
1
- 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.
2
-
3
- ## Method dispatches
4
-
5
- Firstly, a ruby call `foo.bar 1, 2, 3` is compiled into the following javascript:
6
-
7
- ```javascript
8
- foo.$bar(1, 2, 3)
9
- ```
10
-
11
- 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.
12
-
13
- ## Handling method_missing
14
-
15
- 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.
16
-
17
- 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.
18
-
19
- For example, assume the following ruby script:
20
-
21
- ```ruby
22
- first 1, 2, 3
23
- second "wow".to_sym
24
- ```
25
-
26
- 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:
27
-
28
- ```ruby
29
- class BasicObject
30
- def first(*args, &block)
31
- method_missing(:first, *args, &block)
32
- end
33
-
34
- def second(*args, &block)
35
- method_missing(:second, *args, &block)
36
- end
37
-
38
- def to_sym(*args, &block)
39
- method_missing(:to_sym, *args, &block)
40
- end
41
- end
42
- ```
43
-
44
- 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.
45
-
46
- ## Optimising generated code
47
-
48
- To optimise the generated code slightly, we reduce the code output from the compiler into the following javascript:
49
-
50
- ```javascript
51
- Opal.add_stubs(["first", "second", "to_sym"]);
52
- ```
53
-
54
- 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.
55
-
56
- ## Alternative approaches
57
-
58
- 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.