opal 0.9.0.beta2 → 0.9.0.rc1
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.
- checksums.yaml +4 -4
- data/.jshintrc +2 -1
- data/.travis.yml +8 -4
- data/CHANGELOG.md +270 -251
- data/CONTRIBUTING.md +41 -0
- data/README.md +8 -8
- data/Rakefile +1 -1
- data/lib/opal/cli.rb +1 -0
- data/lib/opal/cli_options.rb +2 -2
- data/lib/opal/cli_runners.rb +1 -0
- data/lib/opal/cli_runners/nashorn.rb +58 -0
- data/lib/opal/cli_runners/phantom.js +11 -9
- data/lib/opal/compiler.rb +2 -0
- data/lib/opal/erb.rb +2 -1
- data/lib/opal/nodes/def.rb +15 -6
- data/lib/opal/nodes/helpers.rb +1 -1
- data/lib/opal/nodes/literal.rb +1 -1
- data/lib/opal/nodes/masgn.rb +79 -29
- data/lib/opal/nodes/module.rb +1 -1
- data/lib/opal/nodes/top.rb +6 -2
- data/lib/opal/parser.rb +1 -0
- data/lib/opal/parser/grammar.rb +3160 -3083
- data/lib/opal/parser/grammar.y +39 -11
- data/lib/opal/parser/lexer.rb +15 -13
- data/lib/opal/parser/sexp.rb +5 -0
- data/lib/opal/version.rb +1 -1
- data/opal/corelib/array.rb +21 -6
- data/opal/corelib/basic_object.rb +17 -4
- data/opal/corelib/class.rb +1 -1
- data/opal/corelib/constants.rb +2 -2
- data/opal/corelib/enumerator.rb +2 -0
- data/opal/corelib/hash.rb +50 -50
- data/opal/corelib/helpers.rb +1 -1
- data/opal/corelib/io.rb +9 -6
- data/opal/corelib/kernel.rb +37 -9
- data/opal/corelib/module.rb +6 -17
- data/opal/corelib/nil.rb +4 -0
- data/opal/corelib/number.rb +0 -4
- data/opal/corelib/runtime.js +637 -662
- data/opal/corelib/struct.rb +7 -3
- data/spec/filters/bugs/array.rb +4 -9
- data/spec/filters/bugs/basicobject.rb +1 -15
- data/spec/filters/bugs/date.rb +4 -26
- data/spec/filters/bugs/enumerable.rb +26 -1
- data/spec/filters/bugs/enumerator.rb +4 -4
- data/spec/filters/bugs/exception.rb +1 -7
- data/spec/filters/bugs/float.rb +14 -0
- data/spec/filters/bugs/hash.rb +0 -2
- data/spec/filters/bugs/integer.rb +1 -1
- data/spec/filters/bugs/kernel.rb +47 -66
- data/spec/filters/bugs/language.rb +1 -2
- data/spec/filters/bugs/module.rb +11 -14
- data/spec/filters/bugs/numeric.rb +3 -3
- data/spec/filters/bugs/proc.rb +0 -1
- data/spec/filters/bugs/range.rb +2 -3
- data/spec/filters/bugs/regexp.rb +15 -17
- data/spec/filters/bugs/set.rb +2 -2
- data/spec/filters/bugs/string.rb +29 -5
- data/spec/filters/bugs/{strscan.rb → stringscanner.rb} +9 -10
- data/spec/filters/bugs/struct.rb +0 -4
- data/spec/filters/bugs/time.rb +2 -3
- data/spec/filters/bugs/unboundmethod.rb +3 -0
- data/spec/filters/unsupported/freeze.rb +2 -1
- data/spec/filters/unsupported/taint.rb +2 -0
- data/spec/lib/parser/aref_spec.rb +10 -0
- data/spec/lib/parser/lambda_spec.rb +14 -0
- data/spec/lib/parser/op_asgn_spec.rb +17 -0
- data/spec/lib/parser/return_spec.rb +5 -0
- data/spec/lib/parser/unary_spec.rb +4 -0
- data/spec/lib/sprockets/erb_spec.rb +1 -1
- data/spec/mspec/opal/formatters.rb +159 -0
- data/{lib → spec}/mspec/opal/runner.rb +0 -160
- data/spec/opal/core/hash/internals_spec.rb +162 -162
- data/spec/opal/core/kernel/at_exit_spec.rb +70 -0
- data/spec/opal/core/kernel/extend_spec.rb +1 -1
- data/spec/opal/core/kernel/instance_variables_spec.rb +56 -0
- data/spec/opal/core/language/equal_spec.rb +8 -0
- data/spec/opal/core/language/predefined_spec.rb +1 -1
- data/spec/opal/core/language/ternary_operator_spec.rb +14 -0
- data/spec/opal/core/language/versions/{hash_1.9.rb → hash_1_9_spec.rb} +5 -0
- data/spec/opal/core/module/fixtures/classes.rb +11 -1
- data/spec/opal/core/module/method_lookup_spec.rb +13 -0
- data/spec/opal/core/runtime/super_spec.rb +10 -0
- data/spec/opal/stdlib/native/new_spec.rb +84 -0
- data/spec/opal/stdlib/strscan/scan_spec.rb +11 -0
- data/spec/rubyspecs +6 -9
- data/spec/spec_helper.rb +9 -21
- data/stdlib/date.rb +121 -1
- data/stdlib/js.rb +13 -5
- data/stdlib/json.rb +3 -3
- data/stdlib/nashorn.rb +5 -0
- data/stdlib/nashorn/file.rb +13 -0
- data/stdlib/nashorn/io.rb +2 -0
- data/stdlib/native.rb +12 -4
- data/stdlib/nodejs/io.rb +5 -2
- data/stdlib/opal/platform.rb +19 -0
- data/stdlib/phantomjs.rb +4 -0
- data/stdlib/strscan.rb +1 -1
- data/tasks/building.rake +2 -1
- data/tasks/testing.rake +29 -34
- data/tasks/testing/{phantomjs1-sprockets.js → sprockets-phantomjs.js} +2 -20
- data/vendored-minitest/minitest/test.rb +7 -15
- metadata +32 -9
- data/lib/mspec/opal/main.rb.erb +0 -9
data/CONTRIBUTING.md
CHANGED
|
@@ -23,6 +23,8 @@ the guides.
|
|
|
23
23
|
|
|
24
24
|
If unsure about having satisfied any of the above points ask in the [Gitter channel](https://gitter.im/opal/opal) or just open the issue/pull-request asking for help. There's a good chance someone will help you through the necessary steps.
|
|
25
25
|
|
|
26
|
+
**A note on squashing commits in pull-requests:** There's no need to have a single commit in a PR, rather it's better to have focused commits with specific changes and just avoid the sequence of changes and reverts that tell an interesting story but make the use of `git blame` quite problematic. _That said these are quite loose requirements in the spirit of keeping contributing enjoyable 🤓_
|
|
27
|
+
|
|
26
28
|
## Quick Start
|
|
27
29
|
|
|
28
30
|
Fork https://github.com/opal/opal, then clone the fork to your machine:
|
|
@@ -194,3 +196,42 @@ Array#permutation_truncates_Float_arguments
|
|
|
194
196
|
Array#permutation_returns_an_Enumerator_which_works_as_expected_even_when_the_array_was_modified 0.056
|
|
195
197
|
Array#permutation_generates_from_a_defensive_copy,_ignoring_mutations 0.038
|
|
196
198
|
```
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
## Parser
|
|
202
|
+
|
|
203
|
+
## Enabling debug output from Racc
|
|
204
|
+
|
|
205
|
+
To enable debug output in the Racc grammar set the `RACC_DEBUG` env var and recompile the grammar. While the env variable is set the parser will output the debug info for the parsing process.
|
|
206
|
+
|
|
207
|
+
```bash
|
|
208
|
+
$ export RACC_DEBUG=true
|
|
209
|
+
$ bundle exec rake racc # recompile the grammar
|
|
210
|
+
$ bundle exec bin/opal --sexp -e "42" # ask Opal for the SExp of some code
|
|
211
|
+
|
|
212
|
+
read :tINTEGER(tINTEGER) [42, [1, 0]]
|
|
213
|
+
|
|
214
|
+
shift tINTEGER
|
|
215
|
+
[ (tINTEGER [42, [1, 0]]) ]
|
|
216
|
+
|
|
217
|
+
…cut…
|
|
218
|
+
|
|
219
|
+
shift $end
|
|
220
|
+
[ (program (:int, 42)) ($end [false, [1, 2]]) ($end [false, [1, 2]]) ]
|
|
221
|
+
|
|
222
|
+
goto 403
|
|
223
|
+
[ 0 1 97 403 ]
|
|
224
|
+
|
|
225
|
+
accept
|
|
226
|
+
|
|
227
|
+
(:int, 42)
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
When done unset the env variable and recompile the grammar.
|
|
231
|
+
|
|
232
|
+
```bash
|
|
233
|
+
$ unset RACC_DEBUG
|
|
234
|
+
$ bundle exec rake racc # recompile the grammar
|
|
235
|
+
$ bundle exec bin/opal --sexp -e "42" # ask Opal for the SExp of some code
|
|
236
|
+
(:int, 42)
|
|
237
|
+
```
|
data/README.md
CHANGED
|
@@ -11,7 +11,7 @@ Opal is [hosted on GitHub](http://github.com/opal/opal). Chat is available on *G
|
|
|
11
11
|
Ask questions on [stackoverflow (tag #opalrb)](http://stackoverflow.com/questions/ask?tags=opalrb). Get the [Opalist newsletter](http://opalist.co) for updates and community news.
|
|
12
12
|
|
|
13
13
|
[](http://opalrb.org/docs/api)
|
|
14
|
-
[](https://gitter.im/opal/opal?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
|
|
15
15
|
[](http://stackoverflow.com/questions/ask?tags=opalrb)
|
|
16
16
|
|
|
17
17
|
## Usage
|
|
@@ -29,7 +29,7 @@ puts 'Hello world!'
|
|
|
29
29
|
Then from the terminal
|
|
30
30
|
|
|
31
31
|
```bash
|
|
32
|
-
$ opal --compile app.rb > app.js # The Opal runtime is included by default
|
|
32
|
+
$ opal --compile app.rb > app.js # The Opal runtime is included by default
|
|
33
33
|
# but can be skipped with the --no-opal flag
|
|
34
34
|
```
|
|
35
35
|
|
|
@@ -168,20 +168,20 @@ What code is supposed to run where?
|
|
|
168
168
|
* `opal/` is the runtime+corelib for our implementation (runs in browser).
|
|
169
169
|
* `stdlib/` is our implementation of Ruby's stdlib. It is optional (runs in browser).
|
|
170
170
|
|
|
171
|
-
### lib
|
|
171
|
+
### lib/
|
|
172
172
|
|
|
173
|
-
The `lib` directory holds the Opal parser/compiler used to compile Ruby
|
|
173
|
+
The `lib` directory holds the **Opal parser/compiler** used to compile Ruby
|
|
174
174
|
into JavaScript. It is also built ready for the browser into `opal-parser.js`
|
|
175
175
|
to allow compilation in any JavaScript environment.
|
|
176
176
|
|
|
177
|
-
###
|
|
177
|
+
### opal/
|
|
178
178
|
|
|
179
|
-
This directory holds the Opal runtime and corelib implemented in Ruby and
|
|
179
|
+
This directory holds the **Opal runtime and corelib** implemented in Ruby and
|
|
180
180
|
JavaScript.
|
|
181
181
|
|
|
182
|
-
### stdlib
|
|
182
|
+
### stdlib/
|
|
183
183
|
|
|
184
|
-
Holds the stdlib
|
|
184
|
+
Holds the **stdlib currently supported by Opal**. This includes `Observable`,
|
|
185
185
|
`StringScanner`, `Date`, etc.
|
|
186
186
|
|
|
187
187
|
## Browser support
|
data/Rakefile
CHANGED
data/lib/opal/cli.rb
CHANGED
|
@@ -76,6 +76,7 @@ module Opal
|
|
|
76
76
|
when :nodejs; CliRunners::Nodejs.new(output)
|
|
77
77
|
when :phantomjs; CliRunners::Phantomjs.new(output)
|
|
78
78
|
when :applescript; CliRunners::AppleScript.new(output)
|
|
79
|
+
when :nashorn; CliRunners::Nashorn.new(output)
|
|
79
80
|
else raise ArgumentError, @runner_type.inspect
|
|
80
81
|
end
|
|
81
82
|
end
|
data/lib/opal/cli_options.rb
CHANGED
|
@@ -84,7 +84,7 @@ module Opal
|
|
|
84
84
|
options[:compile] = true
|
|
85
85
|
end
|
|
86
86
|
|
|
87
|
-
on('-R', '--runner RUNNER', %w[nodejs server phantomjs applescript], 'Choose the runner: nodejs (default), server') do |runner|
|
|
87
|
+
on('-R', '--runner RUNNER', %w[nodejs server phantomjs applescript nashorn], 'Choose the runner: nodejs (default), server') do |runner|
|
|
88
88
|
options[:runner] = runner.to_sym
|
|
89
89
|
end
|
|
90
90
|
|
|
@@ -93,7 +93,7 @@ module Opal
|
|
|
93
93
|
options[:port] = port.to_i
|
|
94
94
|
end
|
|
95
95
|
|
|
96
|
-
on('--no-exit', 'Do not append a Kernel#exit at the end of file') do |no_exit|
|
|
96
|
+
on('-E', '--no-exit', 'Do not append a Kernel#exit at the end of file') do |no_exit|
|
|
97
97
|
options[:no_exit] = true
|
|
98
98
|
end
|
|
99
99
|
|
data/lib/opal/cli_runners.rb
CHANGED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
require 'opal/cli_runners'
|
|
2
|
+
require 'opal/paths'
|
|
3
|
+
|
|
4
|
+
module Opal
|
|
5
|
+
module CliRunners
|
|
6
|
+
class Nashorn
|
|
7
|
+
def initialize(output)
|
|
8
|
+
@output ||= output
|
|
9
|
+
end
|
|
10
|
+
attr_reader :output, :exit_status
|
|
11
|
+
|
|
12
|
+
def puts(*args)
|
|
13
|
+
output.puts(*args)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def run(code, argv)
|
|
17
|
+
require 'tempfile'
|
|
18
|
+
tempfile = Tempfile.new('opal-nashorn-runner-')
|
|
19
|
+
tempfile.write code
|
|
20
|
+
tempfile.close
|
|
21
|
+
system_with_output({}, 'jjs', tempfile.path , *argv)
|
|
22
|
+
rescue Errno::ENOENT
|
|
23
|
+
raise MissingNashorn, 'Please install JDK to be able to run Opal scripts.'
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Let's support fake IO objects like StringIO
|
|
27
|
+
def system_with_output(env, *cmd)
|
|
28
|
+
if IO.try_convert(output)
|
|
29
|
+
system(env,*cmd)
|
|
30
|
+
@exit_status = $?.exitstatus
|
|
31
|
+
return
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
if RUBY_PLATFORM == 'java'
|
|
35
|
+
# JRuby has issues in dealing with subprocesses (at least up to 1.7.15)
|
|
36
|
+
# @headius told me it's mostly fixed on master, but while we wait for it
|
|
37
|
+
# to ship here's a tempfile workaround.
|
|
38
|
+
require 'tempfile'
|
|
39
|
+
require 'shellwords'
|
|
40
|
+
tempfile = Tempfile.new('opal-nashorn-output')
|
|
41
|
+
system(env,cmd.shelljoin+" > #{tempfile.path}")
|
|
42
|
+
@exit_status = $?.exitstatus
|
|
43
|
+
captured_output = File.read tempfile.path
|
|
44
|
+
tempfile.close
|
|
45
|
+
else
|
|
46
|
+
require 'open3'
|
|
47
|
+
captured_output, status = Open3.capture2(env,*cmd)
|
|
48
|
+
@exit_status = status.exitstatus
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
output.write captured_output
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
class MissingNashorn < RunnerError
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
@@ -33,12 +33,14 @@ page.onCallback = function(data) {
|
|
|
33
33
|
}
|
|
34
34
|
};
|
|
35
35
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
'
|
|
44
|
-
|
|
36
|
+
|
|
37
|
+
page.onInitialized = function() {
|
|
38
|
+
page.evaluate('function(code) {window.eval(code)}', opal_code)
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
page.setContent("<!doctype html>\n"+
|
|
42
|
+
"<html>"+
|
|
43
|
+
"<head><meta charset='utf-8'/></head><body>"+
|
|
44
|
+
"</body></html>",
|
|
45
|
+
'http://www.example.com');
|
|
46
|
+
|
data/lib/opal/compiler.rb
CHANGED
data/lib/opal/erb.rb
CHANGED
data/lib/opal/nodes/def.rb
CHANGED
|
@@ -79,14 +79,22 @@ module Opal
|
|
|
79
79
|
scope.locals.delete(rest_arg[1])
|
|
80
80
|
end
|
|
81
81
|
|
|
82
|
+
if scope.uses_zuper
|
|
83
|
+
add_local '$zuper'
|
|
84
|
+
add_local '$zuper_index'
|
|
85
|
+
|
|
86
|
+
line "$zuper = [];"
|
|
87
|
+
line "for($zuper_index = 0; $zuper_index < arguments.length; $zuper_index++) {"
|
|
88
|
+
line " $zuper[$zuper_index] = arguments[$zuper_index];"
|
|
89
|
+
line "}"
|
|
90
|
+
end
|
|
91
|
+
|
|
82
92
|
unshift "\n#{current_indent}", scope.to_vars
|
|
83
93
|
|
|
84
94
|
line arity_code if arity_code
|
|
85
95
|
|
|
86
96
|
line stmt_code
|
|
87
97
|
|
|
88
|
-
unshift "var $zuper = $slice.call(arguments, 0);" if scope.uses_zuper
|
|
89
|
-
|
|
90
98
|
if scope.catch_return
|
|
91
99
|
unshift "try {\n"
|
|
92
100
|
line "} catch ($returner) { if ($returner === Opal.returner) { return $returner.$v }"
|
|
@@ -139,11 +147,12 @@ module Opal
|
|
|
139
147
|
def compile_rest_arg
|
|
140
148
|
if rest_arg and rest_arg[1]
|
|
141
149
|
splat = variable(rest_arg[1].to_sym)
|
|
150
|
+
add_local '$splat_index'
|
|
142
151
|
line "var array_size = arguments.length - #{argc};"
|
|
143
152
|
line "if(array_size < 0) array_size = 0;"
|
|
144
153
|
line "var #{splat} = new Array(array_size);"
|
|
145
|
-
line "for(
|
|
146
|
-
line " #{splat}[
|
|
154
|
+
line "for($splat_index = 0; $splat_index < array_size; $splat_index++) {"
|
|
155
|
+
line " #{splat}[$splat_index] = arguments[$splat_index + #{argc}];"
|
|
147
156
|
line "}"
|
|
148
157
|
end
|
|
149
158
|
end
|
|
@@ -199,14 +208,14 @@ module Opal
|
|
|
199
208
|
arg_name = kwarg[1]
|
|
200
209
|
var_name = variable(arg_name.to_s)
|
|
201
210
|
add_local var_name
|
|
202
|
-
line "if ((#{var_name} = $kwargs
|
|
211
|
+
line "if ((#{var_name} = $kwargs.$$smap['#{arg_name}']) == null) {"
|
|
203
212
|
line " #{var_name} = ", expr(kwarg[2])
|
|
204
213
|
line "}"
|
|
205
214
|
when :kwarg
|
|
206
215
|
arg_name = kwarg[1]
|
|
207
216
|
var_name = variable(arg_name.to_s)
|
|
208
217
|
add_local var_name
|
|
209
|
-
line "if ((#{var_name} = $kwargs
|
|
218
|
+
line "if ((#{var_name} = $kwargs.$$smap['#{arg_name}']) == null) {"
|
|
210
219
|
line " throw new Error('expecting keyword arg: #{arg_name}')"
|
|
211
220
|
line "}"
|
|
212
221
|
when :kwrestarg
|
data/lib/opal/nodes/helpers.rb
CHANGED
|
@@ -12,7 +12,7 @@ module Opal
|
|
|
12
12
|
ES3_RESERVED_WORD_EXCLUSIVE = /#{REGEXP_START}(?:int|byte|char|goto|long|final|float|short|double|native|throws|boolean|abstract|volatile|transient|synchronized)#{REGEXP_END}/
|
|
13
13
|
|
|
14
14
|
# Prototype special properties.
|
|
15
|
-
PROTO_SPECIAL_PROPS = /#{REGEXP_START}(?:constructor|__proto__|__parent__|__noSuchMethod__|__count__)#{REGEXP_END}/
|
|
15
|
+
PROTO_SPECIAL_PROPS = /#{REGEXP_START}(?:constructor|displayName|__proto__|__parent__|__noSuchMethod__|__count__)#{REGEXP_END}/
|
|
16
16
|
|
|
17
17
|
# Prototype special methods.
|
|
18
18
|
PROTO_SPECIAL_METHODS = /#{REGEXP_START}(?:hasOwnProperty|valueOf)#{REGEXP_END}/
|
data/lib/opal/nodes/literal.rb
CHANGED
data/lib/opal/nodes/masgn.rb
CHANGED
|
@@ -3,58 +3,108 @@ require 'opal/nodes/base'
|
|
|
3
3
|
module Opal
|
|
4
4
|
module Nodes
|
|
5
5
|
class MassAssignNode < Base
|
|
6
|
-
|
|
6
|
+
# TODO: does this work for cvars?? constants??
|
|
7
|
+
SIMPLE_ASSIGNMENT = [:lasgn, :iasgn, :lvar, :gasgn]
|
|
7
8
|
|
|
9
|
+
handle :masgn
|
|
8
10
|
children :lhs, :rhs
|
|
9
11
|
|
|
10
12
|
def compile
|
|
11
|
-
|
|
12
|
-
len = 0 # how many rhs items are we sure we have
|
|
13
|
+
array = scope.new_temp
|
|
13
14
|
|
|
14
15
|
if rhs.type == :array
|
|
15
|
-
|
|
16
|
-
|
|
16
|
+
push "#{array} = ", expr(rhs)
|
|
17
|
+
compile_masgn(lhs.children, array, rhs.size - 1)
|
|
18
|
+
push ", #{array}" # a mass assignment evaluates to the RHS
|
|
17
19
|
elsif rhs.type == :to_ary
|
|
18
|
-
|
|
20
|
+
retval = scope.new_temp
|
|
21
|
+
push "#{retval} = ", expr(rhs[1])
|
|
22
|
+
push ", #{array} = Opal.to_ary(#{retval})"
|
|
23
|
+
compile_masgn(lhs.children, array)
|
|
24
|
+
push ", #{retval}"
|
|
25
|
+
scope.queue_temp(retval)
|
|
19
26
|
elsif rhs.type == :splat
|
|
20
|
-
push "#{
|
|
27
|
+
push "#{array} = Opal.to_a(", expr(rhs[1]), ")"
|
|
28
|
+
compile_masgn(lhs.children, array)
|
|
29
|
+
push ", #{array}"
|
|
21
30
|
else
|
|
22
31
|
raise "unsupported mlhs type"
|
|
23
32
|
end
|
|
24
33
|
|
|
25
|
-
|
|
26
|
-
|
|
34
|
+
scope.queue_temp(array)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# 'len' is how many rhs items are we sure we have
|
|
38
|
+
def compile_masgn(lhs_items, array, len = nil)
|
|
39
|
+
pre_splat = lhs_items.take_while { |child| child.type != :splat }
|
|
40
|
+
post_splat = lhs_items.drop(pre_splat.size)
|
|
41
|
+
|
|
42
|
+
pre_splat.each_with_index do |child, idx|
|
|
43
|
+
compile_assignment(child, array, idx, len)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
unless post_splat.empty?
|
|
47
|
+
splat = post_splat.shift
|
|
27
48
|
|
|
28
|
-
if
|
|
29
|
-
if part =
|
|
30
|
-
part = part.dup
|
|
31
|
-
|
|
49
|
+
if post_splat.empty? # trailing splat
|
|
50
|
+
if part = splat[1]
|
|
51
|
+
part = part.dup << s(:js_tmp, "$slice.call(#{array}, #{pre_splat.size})")
|
|
52
|
+
push ', '
|
|
32
53
|
push expr(part)
|
|
33
54
|
end
|
|
34
55
|
else
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
56
|
+
tmp = scope.new_temp # end index for items consumed by splat
|
|
57
|
+
push ", #{tmp} = #{array}.length - #{post_splat.size}"
|
|
58
|
+
push ", #{tmp} = (#{tmp} < #{pre_splat.size}) ? #{pre_splat.size} : #{tmp}"
|
|
59
|
+
|
|
60
|
+
if part = splat[1]
|
|
61
|
+
part = part.dup << s(:js_tmp, "$slice.call(#{array}, #{pre_splat.size}, #{tmp})")
|
|
62
|
+
push ', '
|
|
63
|
+
push expr(part)
|
|
39
64
|
end
|
|
40
65
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
elsif child.type == :attrasgn
|
|
48
|
-
part.last << assign
|
|
49
|
-
else
|
|
50
|
-
raise "Bad lhs for masgn"
|
|
66
|
+
post_splat.each_with_index do |child, idx|
|
|
67
|
+
if idx == 0
|
|
68
|
+
compile_assignment(child, array, tmp)
|
|
69
|
+
else
|
|
70
|
+
compile_assignment(child, array, "#{tmp} + #{idx}")
|
|
71
|
+
end
|
|
51
72
|
end
|
|
52
73
|
|
|
53
|
-
|
|
74
|
+
scope.queue_temp(tmp)
|
|
54
75
|
end
|
|
55
76
|
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def compile_assignment(child, array, idx, len = nil)
|
|
80
|
+
if !len || idx >= len
|
|
81
|
+
assign = s(:js_tmp, "(#{array}[#{idx}] == null ? nil : #{array}[#{idx}])")
|
|
82
|
+
else
|
|
83
|
+
assign = s(:js_tmp, "#{array}[#{idx}]")
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
part = child.dup
|
|
87
|
+
if SIMPLE_ASSIGNMENT.include?(child.type)
|
|
88
|
+
part << assign
|
|
89
|
+
elsif child.type == :call
|
|
90
|
+
part[2] = "#{part[2]}=".to_sym
|
|
91
|
+
part.last << assign
|
|
92
|
+
elsif child.type == :attrasgn
|
|
93
|
+
part.last << assign
|
|
94
|
+
elsif child.type == :array
|
|
95
|
+
# nested destructuring
|
|
96
|
+
tmp = scope.new_temp
|
|
97
|
+
push ", (#{tmp} = Opal.to_ary(#{assign[1]})"
|
|
98
|
+
compile_masgn(child.children, tmp)
|
|
99
|
+
push ')'
|
|
100
|
+
scope.queue_temp(tmp)
|
|
101
|
+
return
|
|
102
|
+
else
|
|
103
|
+
raise "Bad child node in masgn LHS: #{child}. LHS: #{lhs}"
|
|
104
|
+
end
|
|
56
105
|
|
|
57
|
-
|
|
106
|
+
push ', '
|
|
107
|
+
push expr(part)
|
|
58
108
|
end
|
|
59
109
|
end
|
|
60
110
|
end
|