opal 0.9.0.beta2 → 0.9.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
[![Inline docs](http://inch-ci.org/github/opal/opal.svg?branch=master&style=flat)](http://opalrb.org/docs/api)
|
14
|
-
[![Gitter
|
14
|
+
[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/opal/opal?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
|
15
15
|
[![Stack Overflow](http://img.shields.io/badge/stackoverflow-%23opalrb-orange.svg?style=flat)](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
|