opal 0.3.20 → 0.3.21
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.
- data/.gitignore +2 -7
- data/.rspec +2 -0
- data/.travis.yml +11 -0
- data/Gemfile +8 -2
- data/LICENSE +2 -3
- data/README.md +106 -239
- data/Rakefile +58 -16
- data/bin/opal +1 -0
- data/core/array.rb +180 -160
- data/core/basic_object.rb +8 -4
- data/core/boolean.rb +6 -6
- data/core/class.rb +9 -15
- data/core/dir.rb +89 -0
- data/core/enumerable.rb +83 -86
- data/core/error.rb +9 -4
- data/core/file.rb +85 -0
- data/core/hash.rb +67 -67
- data/core/kernel.rb +38 -42
- data/core/module.rb +57 -54
- data/core/numeric.rb +41 -41
- data/core/proc.rb +1 -5
- data/core/range.rb +11 -11
- data/core/regexp.rb +27 -22
- data/core/runtime.js +152 -221
- data/core/string.rb +86 -73
- data/core/time.rb +22 -18
- data/docs/post.html +9 -0
- data/docs/pre.html +32 -0
- data/lib/opal.rb +43 -3
- data/lib/opal/builder.rb +9 -26
- data/lib/opal/grammar.rb +1 -1
- data/lib/opal/grammar.y +1 -1
- data/lib/opal/lexer.rb +21 -15
- data/lib/opal/parser.rb +100 -111
- data/lib/opal/rake_task.rb +66 -0
- data/lib/opal/scope.rb +13 -5
- data/lib/opal/version.rb +1 -1
- data/opal.gemspec +2 -0
- data/spec/browser_spec.rb +28 -0
- data/spec/builder/lib_name_for_spec.rb +1 -6
- data/spec/grammar/alias_spec.rb +1 -1
- data/spec/grammar/and_spec.rb +1 -1
- data/spec/grammar/array_spec.rb +1 -1
- data/spec/grammar/attrasgn_spec.rb +1 -1
- data/spec/grammar/begin_spec.rb +1 -1
- data/spec/grammar/block_spec.rb +1 -1
- data/spec/grammar/break_spec.rb +1 -1
- data/spec/grammar/call_spec.rb +1 -1
- data/spec/grammar/class_spec.rb +1 -1
- data/spec/grammar/const_spec.rb +1 -1
- data/spec/grammar/cvar_spec.rb +1 -1
- data/spec/grammar/def_spec.rb +1 -1
- data/spec/grammar/false_spec.rb +1 -1
- data/spec/grammar/file_spec.rb +1 -1
- data/spec/grammar/gvar_spec.rb +1 -1
- data/spec/grammar/hash_spec.rb +1 -1
- data/spec/grammar/iasgn_spec.rb +1 -1
- data/spec/grammar/if_spec.rb +1 -1
- data/spec/grammar/iter_spec.rb +1 -1
- data/spec/grammar/ivar_spec.rb +1 -1
- data/spec/grammar/lambda_spec.rb +1 -1
- data/spec/grammar/lasgn_spec.rb +1 -1
- data/spec/grammar/line_spec.rb +1 -1
- data/spec/grammar/lvar_spec.rb +1 -1
- data/spec/grammar/masgn_spec.rb +1 -1
- data/spec/grammar/module_spec.rb +1 -1
- data/spec/grammar/nil_spec.rb +1 -1
- data/spec/grammar/not_spec.rb +1 -1
- data/spec/grammar/op_asgn1_spec.rb +1 -1
- data/spec/grammar/op_asgn2_spec.rb +1 -1
- data/spec/grammar/or_spec.rb +1 -1
- data/spec/grammar/return_spec.rb +1 -1
- data/spec/grammar/sclass_spec.rb +1 -1
- data/spec/grammar/self_spec.rb +1 -1
- data/spec/grammar/str_spec.rb +1 -1
- data/spec/grammar/super_spec.rb +1 -1
- data/spec/grammar/true_spec.rb +1 -1
- data/spec/grammar/undef_spec.rb +1 -1
- data/spec/grammar/unless_spec.rb +1 -1
- data/spec/grammar/while_spec.rb +1 -1
- data/spec/grammar/xstr_spec.rb +1 -1
- data/spec/grammar/yield_spec.rb +1 -1
- data/spec/spec_helper.rb +6 -1
- data/test/core/array/minus_spec.rb +13 -0
- data/test/core/enumerable/drop_while_spec.rb +0 -5
- data/test/core/range/case_compare_spec.rb +0 -1
- data/test/index.html +1 -1
- data/test/index.min.html +12 -0
- data/test/language/alias_spec.rb +0 -4
- data/test/language/fixtures/next.rb +62 -0
- data/test/language/metaclass_spec.rb +4 -4
- data/test/language/next_spec.rb +0 -63
- data/test/language/send_spec.rb +0 -5
- data/test/language/singleton_class_spec.rb +4 -0
- data/test/opal/array/subclassing_spec.rb +1 -1
- data/test/opal/class/bridge_class_spec.rb +2 -2
- data/test/opal/runtime/class_hierarchy_spec.rb +1 -2
- data/test/opal/runtime/method_missing_spec.rb +17 -0
- data/test/spec_helper.rb +4 -1
- metadata +32 -28
- data/docs/CNAME +0 -1
- data/docs/Rakefile +0 -55
- data/docs/css/styles.css +0 -50
- data/docs/css/syntax.css +0 -63
- data/docs/layout/post.html +0 -3
- data/docs/layout/pre.html +0 -11
- data/examples/dependencies/.gitignore +0 -1
- data/examples/dependencies/Gemfile +0 -6
- data/examples/dependencies/README.md +0 -41
- data/examples/dependencies/Rakefile +0 -10
- data/examples/dependencies/app.rb +0 -19
- data/examples/dependencies/build/.gitkeep +0 -0
- data/examples/dependencies/index.html +0 -13
- data/examples/hello_world/.gitignore +0 -1
- data/examples/hello_world/Gemfile +0 -3
- data/examples/hello_world/README.md +0 -27
- data/examples/hello_world/Rakefile +0 -23
- data/examples/hello_world/app.rb +0 -7
- data/examples/hello_world/index.html +0 -12
- data/lib/opal/builder_task.rb +0 -91
- data/spec/builder/build_order_spec.rb +0 -20
- data/test/opal/runtime/_methods_spec.rb +0 -48
data/.gitignore
CHANGED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
CHANGED
|
@@ -6,6 +6,12 @@ gem "rake"
|
|
|
6
6
|
gem "racc"
|
|
7
7
|
|
|
8
8
|
group :browser do
|
|
9
|
-
gem
|
|
10
|
-
gem 'opal-dom'
|
|
9
|
+
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
|
+
end
|
|
13
|
+
|
|
14
|
+
group :docs do
|
|
15
|
+
gem "redcarpet"
|
|
16
|
+
gem "albino"
|
|
11
17
|
end
|
data/LICENSE
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
Copyright (C)
|
|
1
|
+
Copyright (C) 2012 by Adam Beynon
|
|
2
2
|
|
|
3
3
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
4
4
|
of this software and associated documentation files (the "Software"), to deal
|
|
@@ -16,5 +16,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
16
16
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
17
17
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
18
18
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
19
|
-
THE SOFTWARE.
|
|
20
|
-
|
|
19
|
+
THE SOFTWARE.
|
data/README.md
CHANGED
|
@@ -19,15 +19,11 @@ is a Freenode IRC channel at `#opal`.
|
|
|
19
19
|
The Opal runtime and corelib are distributed here, and are required to
|
|
20
20
|
run any code generated by opal.
|
|
21
21
|
|
|
22
|
-
[Opal version 0.3.
|
|
22
|
+
[Opal version 0.3.21](http://opalrb.org/opal.js) _(13.1kb Minified And Gzipped)_
|
|
23
23
|
|
|
24
24
|
## Installation
|
|
25
25
|
|
|
26
|
-
Opal
|
|
27
|
-
|
|
28
|
-
gem install opal
|
|
29
|
-
|
|
30
|
-
Or add to your Gemfile:
|
|
26
|
+
Opal should be added to your Gemfile:
|
|
31
27
|
|
|
32
28
|
```ruby
|
|
33
29
|
gem "opal"
|
|
@@ -35,139 +31,150 @@ gem "opal"
|
|
|
35
31
|
|
|
36
32
|
## Usage
|
|
37
33
|
|
|
38
|
-
|
|
39
|
-
|
|
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`:
|
|
40
37
|
|
|
41
38
|
```ruby
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
Opal.parse("puts 'hello world'")
|
|
39
|
+
# app.rb
|
|
40
|
+
puts "Hello world"
|
|
45
41
|
```
|
|
46
42
|
|
|
47
|
-
|
|
43
|
+
Then create a rake task similar to:
|
|
48
44
|
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
45
|
+
```ruby
|
|
46
|
+
# Rakefile
|
|
47
|
+
require 'opal/rake_task'
|
|
48
|
+
|
|
49
|
+
Opal::RakeTask.new do |t|
|
|
50
|
+
t.files = ['app.rb']
|
|
51
|
+
end
|
|
54
52
|
```
|
|
55
53
|
|
|
56
|
-
|
|
57
|
-
global javascript variable that holds all the ruby classes and methods.
|
|
58
|
-
`Opal.top` points to the top object in opal, so any file will have this
|
|
59
|
-
object as its top level `self` variable.
|
|
54
|
+
### Building the app
|
|
60
55
|
|
|
61
|
-
|
|
56
|
+
Building the app is as simple as running:
|
|
62
57
|
|
|
63
|
-
|
|
64
|
-
|
|
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
65
|
|
|
66
66
|
```ruby
|
|
67
|
-
|
|
67
|
+
Opal::RakeTask.new do |t|
|
|
68
|
+
t.files = ['app.rb']
|
|
69
|
+
t.name = 'my_awesome_app'
|
|
70
|
+
end
|
|
71
|
+
```
|
|
68
72
|
|
|
69
|
-
|
|
73
|
+
### Building opal runtime
|
|
70
74
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
src = File.read 'app.rb'
|
|
74
|
-
js = Opal.parse src
|
|
75
|
+
To run the app in the browser, the opal runtime is required. This can
|
|
76
|
+
be built using:
|
|
75
77
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
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'
|
|
79
90
|
end
|
|
80
91
|
```
|
|
81
92
|
|
|
82
|
-
|
|
83
|
-
write it out to a file ready to load in a web browser.
|
|
93
|
+
The output directory will be created if it doesn't exist.
|
|
84
94
|
|
|
85
|
-
###
|
|
95
|
+
### Running the app
|
|
86
96
|
|
|
87
|
-
The
|
|
88
|
-
|
|
97
|
+
The two compiled files need to be added to a html page so that they
|
|
98
|
+
can run in the browser:
|
|
89
99
|
|
|
90
100
|
```html
|
|
91
101
|
<!doctype html>
|
|
92
102
|
<html>
|
|
93
103
|
<head>
|
|
94
|
-
<title>
|
|
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>
|
|
95
113
|
</head>
|
|
96
114
|
<body>
|
|
97
|
-
<script src="opal.js"></script>
|
|
98
|
-
<script src="app.js"></script>
|
|
99
115
|
</body>
|
|
100
116
|
</html>
|
|
101
117
|
```
|
|
102
118
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
see the message printed to the console.
|
|
119
|
+
If you open the html file, observe the console and you should see
|
|
120
|
+
`"Hello World"` printed to the console.
|
|
106
121
|
|
|
107
|
-
|
|
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.
|
|
108
125
|
|
|
109
|
-
|
|
110
|
-
opal. For more complex apps with dependencies, Opal provides useful
|
|
111
|
-
rake tasks to get started. Assuming opal is in your lib path, create
|
|
112
|
-
a `Rakefile` similar to:
|
|
126
|
+
### Adding dependencies
|
|
113
127
|
|
|
114
|
-
|
|
115
|
-
|
|
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.
|
|
116
131
|
|
|
117
|
-
|
|
132
|
+
`opal-dom` first needs to be installed as a gem (currently it is only
|
|
133
|
+
available from git):
|
|
118
134
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
end
|
|
135
|
+
```ruby
|
|
136
|
+
# Gemfile
|
|
137
|
+
gem "opal"
|
|
138
|
+
gem "opal-dom", :git => 'git://github.com/adambeynon/opal-dom.git'
|
|
124
139
|
```
|
|
125
140
|
|
|
126
|
-
|
|
127
|
-
dependencies.
|
|
128
|
-
|
|
129
|
-
### Building dependencies
|
|
130
|
-
|
|
131
|
-
To build the opal runtime `opal.js`, as well as `opal-spec` into
|
|
132
|
-
`build/`, run the simple rake task:
|
|
141
|
+
Then add it to the dependencies to build:
|
|
133
142
|
|
|
134
143
|
```ruby
|
|
135
|
-
|
|
144
|
+
Opal::RakeTask.new do |t|
|
|
145
|
+
t.files = ['app.rb']
|
|
146
|
+
t.dependencies = ['opal-dom']
|
|
147
|
+
end
|
|
136
148
|
```
|
|
137
149
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
Gemfile as `gem "opal-spec"` and run `bundle install`.
|
|
150
|
+
Running `rake opal:dependencies` now will also build
|
|
151
|
+
`build/opal-dom.js`.
|
|
141
152
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
To build the listed files into your application, run:
|
|
153
|
+
We can now update our application code:
|
|
145
154
|
|
|
146
155
|
```ruby
|
|
147
|
-
|
|
156
|
+
# app.rb
|
|
157
|
+
require 'opal-dom'
|
|
158
|
+
|
|
159
|
+
alert "Hello!"
|
|
148
160
|
```
|
|
149
161
|
|
|
150
|
-
|
|
151
|
-
filename, change the `name` property in the raketask.
|
|
162
|
+
And rebuild:
|
|
152
163
|
|
|
153
|
-
|
|
164
|
+
```
|
|
165
|
+
rake opal:build
|
|
166
|
+
```
|
|
154
167
|
|
|
155
|
-
|
|
168
|
+
And add `opal-dom` to the html page:
|
|
156
169
|
|
|
157
170
|
```html
|
|
158
|
-
|
|
159
|
-
<
|
|
160
|
-
<
|
|
161
|
-
<title>Test Opal App</title>
|
|
162
|
-
</head>
|
|
163
|
-
<body>
|
|
164
|
-
<script src="build/opal.js"></script>
|
|
165
|
-
<script src="build/opal-spec.js"></script>
|
|
166
|
-
<script src="build/my-first-app.js"></script>
|
|
167
|
-
</body>
|
|
168
|
-
</html>
|
|
171
|
+
<script src="build/opal.js"></script>
|
|
172
|
+
<script src="build/opal-dom.js"></script>
|
|
173
|
+
<script src="build/app.js"></script>
|
|
169
174
|
```
|
|
170
175
|
|
|
176
|
+
Now running the app should cause an alert box to display.
|
|
177
|
+
|
|
171
178
|
## Features And Implementation
|
|
172
179
|
|
|
173
180
|
Opal is a source-to-source compiler, so there is no VM as such and the
|
|
@@ -176,7 +183,7 @@ directly to underlying javascript features and objects where possible.
|
|
|
176
183
|
|
|
177
184
|
### Literals
|
|
178
185
|
|
|
179
|
-
**self** is always compiled to `
|
|
186
|
+
**self** is always compiled to `self`. Any context inside the generated
|
|
180
187
|
code is usually a function body; whether it be a method body, a block,
|
|
181
188
|
a class/module body or the file itself.
|
|
182
189
|
|
|
@@ -195,7 +202,7 @@ files points to a special object which is just an instance of the ruby
|
|
|
195
202
|
nil # => nil
|
|
196
203
|
true # => true
|
|
197
204
|
false # => false
|
|
198
|
-
self # =>
|
|
205
|
+
self # => self
|
|
199
206
|
```
|
|
200
207
|
|
|
201
208
|
#### Strings
|
|
@@ -262,94 +269,6 @@ range instances.
|
|
|
262
269
|
3...7 # => __range(3, 7, false)
|
|
263
270
|
```
|
|
264
271
|
|
|
265
|
-
### Classes and Modules
|
|
266
|
-
|
|
267
|
-
A compiled class or module body is simply just an anonymous javascript
|
|
268
|
-
function that is used to keep any internal variables from escaping.
|
|
269
|
-
|
|
270
|
-
Classes and modules themselves are created as named functions (which is
|
|
271
|
-
used purely to aid debugging). Classes and modules may also be
|
|
272
|
-
re-opended, so they are put through a runtime function `__klass` for
|
|
273
|
-
classes, and `__module` for modules.
|
|
274
|
-
|
|
275
|
-
For example, the `Kernel` module is generated as:
|
|
276
|
-
|
|
277
|
-
```javascript
|
|
278
|
-
(function(__base) {
|
|
279
|
-
function Kernel(){};
|
|
280
|
-
Kernel = __module(__base, "Kernel", Kernel);
|
|
281
|
-
var Kernel_prototype = Kernel.prototype;
|
|
282
|
-
|
|
283
|
-
Kernel_prototype.$class = function() {
|
|
284
|
-
return this._real;
|
|
285
|
-
};
|
|
286
|
-
|
|
287
|
-
Kernel._donate('$class', ...);
|
|
288
|
-
})(__scope);
|
|
289
|
-
```
|
|
290
|
-
|
|
291
|
-
Firstly, the `__scope` is passed into the function which is used
|
|
292
|
-
for defining constants, which means that if `Kernel` gets defined
|
|
293
|
-
here then it can be set as a constant for the given scope. The
|
|
294
|
-
named function (Kernel) follows, as well as the `__module()` call
|
|
295
|
-
which simply sets the up the module if it doesn't already exist. If
|
|
296
|
-
it does exist, then it overwrites the previous `Kernel` local variable.
|
|
297
|
-
|
|
298
|
-
Next, `Kernel_prototype` is made a local variable to improve
|
|
299
|
-
minimization of the code, then all the Kernel methods are set on the
|
|
300
|
-
prototype. Modules cannot be instantiated in Opal (just like ruby), but
|
|
301
|
-
the use of prototypes is to improve performance.
|
|
302
|
-
|
|
303
|
-
Finally, the call to `Kernel._donate()` is to pass any defined methods
|
|
304
|
-
into classes that have included `Kernel`, which is just `Object`. This
|
|
305
|
-
method then adds all of Kernels methods into Objects prototype as this
|
|
306
|
-
is the most efficient way to try and emulate rubys method chain.
|
|
307
|
-
|
|
308
|
-
### Methods
|
|
309
|
-
|
|
310
|
-
A ruby method is just compiled directly into a function definition.
|
|
311
|
-
These functions are added to the constructor's prototype so they can
|
|
312
|
-
be called just like any javascript function. All ruby methods are
|
|
313
|
-
defined with a `$` prefix to try and isolate them from javascript
|
|
314
|
-
methods.
|
|
315
|
-
|
|
316
|
-
#### Method Calls
|
|
317
|
-
|
|
318
|
-
All method arguments are passed to the native function just like normal
|
|
319
|
-
javascript function calls. Therefore, the given ruby code:
|
|
320
|
-
|
|
321
|
-
```ruby
|
|
322
|
-
do_something 1, 2, 3
|
|
323
|
-
self.length
|
|
324
|
-
[1, 2, 3].push 5
|
|
325
|
-
```
|
|
326
|
-
|
|
327
|
-
Will be compiled into the easy to read javascript:
|
|
328
|
-
|
|
329
|
-
```javascript
|
|
330
|
-
this.$do_something(1, 2, 3);
|
|
331
|
-
this.$length();
|
|
332
|
-
[1, 2, 3].$push(5);
|
|
333
|
-
```
|
|
334
|
-
|
|
335
|
-
There are some certain characters which are valid as ruby method names
|
|
336
|
-
but not as javascript identifiers. These method calls are encoded to
|
|
337
|
-
keep the generated method names sane.
|
|
338
|
-
|
|
339
|
-
```ruby
|
|
340
|
-
self.loaded? # => this.$loaded$p()
|
|
341
|
-
self.load! # => this.$load$b()
|
|
342
|
-
self.loaded = true # => this.$loaded$e(true)
|
|
343
|
-
self << :bar # => this.$lshift$("bar")
|
|
344
|
-
```
|
|
345
|
-
|
|
346
|
-
Finally, method calls with splat arguments are also supported:
|
|
347
|
-
|
|
348
|
-
```ruby
|
|
349
|
-
self.push *[1, 2, 3]
|
|
350
|
-
# => this.$push.apply(this, [1, 2, 3])
|
|
351
|
-
```
|
|
352
|
-
|
|
353
272
|
#### Optimized Math Operators
|
|
354
273
|
|
|
355
274
|
In ruby, all math operators are method calls, but compiling this into
|
|
@@ -364,7 +283,7 @@ if so then to just carry out the math call.
|
|
|
364
283
|
This ruby code will then be compiled into the following javascript:
|
|
365
284
|
|
|
366
285
|
```javascript
|
|
367
|
-
(a = 3, b = 4, typeof(a) === "number" ? a + b :
|
|
286
|
+
(a = 3, b = 4, typeof(a) === "number" ? a + b : /* method call */)
|
|
368
287
|
```
|
|
369
288
|
|
|
370
289
|
This ternary statement falls back on sending a method to the receiver
|
|
@@ -372,68 +291,10 @@ so all non-numeric receivers will still have the normal method call
|
|
|
372
291
|
being sent. This optimization makes math operators a **lot faster**.
|
|
373
292
|
Currently, the optimized method calls are `+`, `-`, `*` and `/`.
|
|
374
293
|
|
|
375
|
-
|
|
294
|
+
### method_missing
|
|
376
295
|
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
```ruby
|
|
381
|
-
def to_s
|
|
382
|
-
inspect
|
|
383
|
-
end
|
|
384
|
-
```
|
|
385
|
-
|
|
386
|
-
This would generate the following javascript. (`Array_prototype` is
|
|
387
|
-
an example and would assume this method definition is inside the
|
|
388
|
-
`Array` class body).
|
|
389
|
-
|
|
390
|
-
```javascript
|
|
391
|
-
Array_prototype.$to_s = function() {
|
|
392
|
-
return this.$inspect();
|
|
393
|
-
};
|
|
394
|
-
```
|
|
395
|
-
|
|
396
|
-
The defined name retains the `$` prefix outlined above, and the `self`
|
|
397
|
-
value for the method is `this`, which will be the receiver.
|
|
398
|
-
|
|
399
|
-
Normal arguments, splat args and optional args are all supported:
|
|
400
|
-
|
|
401
|
-
```ruby
|
|
402
|
-
def norm(a, b, c)
|
|
403
|
-
|
|
404
|
-
end
|
|
405
|
-
|
|
406
|
-
def opt(a, b = 100)
|
|
407
|
-
|
|
408
|
-
end
|
|
409
|
-
|
|
410
|
-
def rest(a, *b)
|
|
411
|
-
|
|
412
|
-
end
|
|
413
|
-
```
|
|
414
|
-
|
|
415
|
-
The generated code reads as expected:
|
|
416
|
-
|
|
417
|
-
```javascript
|
|
418
|
-
Array_prototype.$norm = function(a, b, c) {
|
|
419
|
-
return nil;
|
|
420
|
-
};
|
|
421
|
-
|
|
422
|
-
Array_prototype.$opt = function(a, b) {
|
|
423
|
-
if (b == null) b = 100;
|
|
424
|
-
return nil;
|
|
425
|
-
};
|
|
426
|
-
|
|
427
|
-
Array_prototype.$rest = function(a, b) {
|
|
428
|
-
b = __slice.call(arguments, 1);
|
|
429
|
-
return nil;
|
|
430
|
-
};
|
|
431
|
-
```
|
|
432
|
-
|
|
433
|
-
Currently, in opal there is no argument length checking to ensure that
|
|
434
|
-
the correct number of arguments get passed to a function. This can be
|
|
435
|
-
enabled in debug mode, but is not included in production builds as it
|
|
436
|
-
adds a lot of overhead to **every** method call.
|
|
296
|
+
Method missing is fully supported in Opal. It is implemented as
|
|
297
|
+
efficiently as possible.
|
|
437
298
|
|
|
438
299
|
### Logic and conditionals
|
|
439
300
|
|
|
@@ -696,6 +557,12 @@ Opal is released under the MIT license.
|
|
|
696
557
|
|
|
697
558
|
## Change Log
|
|
698
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
|
+
|
|
699
566
|
**0.3.20** _(23 June 2012)_
|
|
700
567
|
|
|
701
568
|
* Merge JSON into core. JSON module and various #to_json methods are
|