ruby2js 1.15.1 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. data/lib/ruby2js.rb +36 -36
  2. data/lib/ruby2js/converter.rb +59 -20
  3. data/lib/ruby2js/converter/arg.rb +1 -1
  4. data/lib/ruby2js/converter/args.rb +1 -1
  5. data/lib/ruby2js/converter/array.rb +3 -4
  6. data/lib/ruby2js/converter/begin.rb +15 -1
  7. data/lib/ruby2js/converter/block.rb +6 -5
  8. data/lib/ruby2js/converter/boolean.rb +1 -1
  9. data/lib/ruby2js/converter/break.rb +1 -1
  10. data/lib/ruby2js/converter/case.rb +27 -7
  11. data/lib/ruby2js/converter/casgn.rb +5 -2
  12. data/lib/ruby2js/converter/class.rb +41 -11
  13. data/lib/ruby2js/converter/const.rb +1 -1
  14. data/lib/ruby2js/converter/cvar.rb +4 -3
  15. data/lib/ruby2js/converter/cvasgn.rb +5 -6
  16. data/lib/ruby2js/converter/def.rb +15 -3
  17. data/lib/ruby2js/converter/defined.rb +1 -1
  18. data/lib/ruby2js/converter/defs.rb +7 -3
  19. data/lib/ruby2js/converter/dstr.rb +3 -3
  20. data/lib/ruby2js/converter/for.rb +7 -10
  21. data/lib/ruby2js/converter/hash.rb +70 -34
  22. data/lib/ruby2js/converter/if.rb +35 -13
  23. data/lib/ruby2js/converter/in.rb +1 -1
  24. data/lib/ruby2js/converter/ivasgn.rb +1 -1
  25. data/lib/ruby2js/converter/kwbegin.rb +20 -20
  26. data/lib/ruby2js/converter/literal.rb +1 -1
  27. data/lib/ruby2js/converter/logical.rb +4 -8
  28. data/lib/ruby2js/converter/next.rb +1 -1
  29. data/lib/ruby2js/converter/nil.rb +1 -1
  30. data/lib/ruby2js/converter/nthref.rb +1 -1
  31. data/lib/ruby2js/converter/opasgn.rb +3 -3
  32. data/lib/ruby2js/converter/regexp.rb +12 -9
  33. data/lib/ruby2js/converter/return.rb +3 -3
  34. data/lib/ruby2js/converter/self.rb +2 -2
  35. data/lib/ruby2js/converter/send.rb +31 -30
  36. data/lib/ruby2js/converter/super.rb +8 -11
  37. data/lib/ruby2js/converter/sym.rb +1 -1
  38. data/lib/ruby2js/converter/undef.rb +9 -2
  39. data/lib/ruby2js/converter/var.rb +1 -1
  40. data/lib/ruby2js/converter/vasgn.rb +13 -5
  41. data/lib/ruby2js/converter/while.rb +2 -1
  42. data/lib/ruby2js/converter/whilepost.rb +2 -1
  43. data/lib/ruby2js/converter/xstr.rb +4 -3
  44. data/lib/ruby2js/execjs.rb +3 -3
  45. data/lib/ruby2js/filter/camelCase.rb +8 -8
  46. data/lib/ruby2js/filter/functions.rb +64 -65
  47. data/lib/ruby2js/filter/react.rb +44 -16
  48. data/lib/ruby2js/filter/require.rb +4 -1
  49. data/lib/ruby2js/filter/underscore.rb +21 -21
  50. data/lib/ruby2js/serializer.rb +347 -0
  51. data/lib/ruby2js/version.rb +3 -3
  52. data/ruby2js.gemspec +3 -3
  53. metadata +3 -2
@@ -19,16 +19,14 @@ module Ruby2JS
19
19
  lgroup = LOGICAL.include?( left.type ) &&
20
20
  op_index < operator_index( left.type )
21
21
  lgroup = true if left and left.type == :begin
22
- left = parse left
23
- left = "(#{ left })" if lgroup
24
22
 
25
23
  rgroup = LOGICAL.include?( right.type ) &&
26
24
  op_index < operator_index( right.type )
27
25
  rgroup = true if right.type == :begin
28
- right = parse right
29
- right = "(#{ right })" if rgroup
30
26
 
31
- "#{ left } #{ type==:and ? '&&' : '||' } #{ right }"
27
+ put '(' if lgroup; parse left; put ')' if lgroup
28
+ put (type==:and ? ' && ' : ' || ')
29
+ put '(' if rgroup; parse right; put ')' if rgroup
32
30
  end
33
31
 
34
32
  # (not
@@ -49,10 +47,8 @@ module Ruby2JS
49
47
  group = LOGICAL.include?( expr.type ) &&
50
48
  operator_index( :not ) < operator_index( expr.type )
51
49
  group = true if expr and expr.type == :begin
52
- expr = parse expr
53
- expr = "(#{ expr })" if group
54
50
 
55
- "!#{ expr }"
51
+ put '!'; put '(' if group; parse expr; put ')' if group
56
52
  end
57
53
  end
58
54
  end
@@ -6,7 +6,7 @@ module Ruby2JS
6
6
 
7
7
  handle :next do |n=nil|
8
8
  raise NotImplementedError, "next argument #{ n.inspect }" if n
9
- @next_token.to_s
9
+ put @next_token.to_s
10
10
  end
11
11
  end
12
12
  end
@@ -4,7 +4,7 @@ module Ruby2JS
4
4
  # (nil)
5
5
 
6
6
  handle :nil do
7
- 'null'
7
+ put 'null'
8
8
  end
9
9
  end
10
10
  end
@@ -4,7 +4,7 @@ module Ruby2JS
4
4
  # (nthref 1)
5
5
 
6
6
  handle :nth_ref do |var|
7
- "$#{var}"
7
+ put "$#{var}"
8
8
  end
9
9
  end
10
10
  end
@@ -14,12 +14,12 @@ module Ruby2JS
14
14
 
15
15
  if [:+, :-].include?(op) and value.type==:int and value.children==[1]
16
16
  if @state == :statement
17
- "#{ parse var }#{ op }#{ op }"
17
+ parse var; put "#{ op }#{ op }"
18
18
  else
19
- "#{ op }#{ op }#{ parse var }"
19
+ put "#{ op }#{ op }"; parse var
20
20
  end
21
21
  else
22
- "#{ parse var } #{ op }= #{ parse value }"
22
+ parse var; put " #{ op }= "; parse value
23
23
  end
24
24
  end
25
25
 
@@ -17,27 +17,30 @@ module Ruby2JS
17
17
  str = parts.map {|part| part.children.first}.join
18
18
  str = str.gsub(/ #.*/,'').gsub(/\s/,'') if extended
19
19
  unless str.include? '/'
20
- return "/#{ str }/#{ opts.join }"
20
+ return put "/#{ str }/#{ opts.join }"
21
21
  end
22
- str = str.inspect
22
+ put "new RegExp(#{ str.inspect }"
23
23
  else
24
- parts.map! do |part|
24
+ put 'new RegExp('
25
+
26
+ parts.each_with_index do |part, index|
27
+ put ' + ' unless index == 0
28
+
25
29
  if part.type == :str
26
30
  str = part.children.first
27
31
  str = str.gsub(/ #.*/,'').gsub(/\s/,'') if extended
28
- str.inspect
32
+ put str.inspect
29
33
  else
30
34
  parse part
31
35
  end
32
36
  end
33
- str = parts.join(' + ')
34
37
  end
35
38
 
36
- if opts.empty?
37
- "new RegExp(#{ str })"
38
- else
39
- "new RegExp(#{ str }, #{ opts.join.inspect})"
39
+ unless opts.empty?
40
+ put ", #{ opts.join.inspect}"
40
41
  end
42
+
43
+ put ')'
41
44
  end
42
45
  end
43
46
  end
@@ -6,9 +6,9 @@ module Ruby2JS
6
6
 
7
7
  handle :return do |value=nil|
8
8
  if value
9
- "return #{ parse value }"
9
+ put 'return '; parse value
10
10
  else
11
- "return"
11
+ put 'return'
12
12
  end
13
13
  end
14
14
 
@@ -24,7 +24,7 @@ module Ruby2JS
24
24
  end
25
25
 
26
26
  if EXPRESSIONS.include? block.last.type
27
- block.push s(:return, block.pop)
27
+ block.push @ast.updated(:return, [block.pop])
28
28
  elsif block.last.type == :if
29
29
  node = block.pop
30
30
  if node.children[1] and node.children[2] and
@@ -6,9 +6,9 @@ module Ruby2JS
6
6
  handle :self do
7
7
  if @block_depth and @block_depth > 1
8
8
  @block_this = true
9
- 'self'
9
+ put 'self'
10
10
  else
11
- 'this'
11
+ put 'this'
12
12
  end
13
13
  end
14
14
  end
@@ -13,7 +13,7 @@ module Ruby2JS
13
13
  # interpretation as an attribute vs a function call with zero parameters.
14
14
  # Sendw forces parameters to be placed on separate lines.
15
15
 
16
- handle :send, :sendw, :attr do |receiver, method, *args|
16
+ handle :send, :sendw, :attr, :call do |receiver, method, *args|
17
17
  ast = @ast
18
18
 
19
19
  width = ((ast.type == :sendw && !@nl.empty?) ? 0 : @width)
@@ -32,8 +32,9 @@ module Ruby2JS
32
32
  if [:call, :[]].include? method and receiver and receiver.type == :block
33
33
  t2,m2,*args2 = receiver.children.first.children
34
34
  if not t2 and [:lambda, :proc].include? m2 and args2.length == 0
35
- receiver = (@state == :statement ? group(receiver) : parse(receiver))
36
- return parse s(:send, nil, receiver, *args)
35
+ (@state == :statement ? group(receiver) : parse(receiver))
36
+ put '('; parse_all *args, join: ', '; put ')'
37
+ return
37
38
  end
38
39
  end
39
40
 
@@ -62,31 +63,36 @@ module Ruby2JS
62
63
  parse s(:not, receiver)
63
64
 
64
65
  elsif method == :[]
65
- "#{ parse receiver }[#{ args.map {|arg| parse arg}.join(', ') }]"
66
+ parse receiver; put '['; parse_all *args, join: ', '; put ']'
66
67
 
67
68
  elsif method == :[]=
68
- "#{ parse receiver }[#{ args[0..-2].map {|arg| parse arg}.join(', ') }] = #{ parse args[-1] }"
69
+ parse receiver; put '['; parse_all *args[0..-2], join: ', '; put '] = '
70
+ parse args[-1]
69
71
 
70
72
  elsif [:-@, :+@, :~, '~'].include? method
71
- "#{ method.to_s[0] }#{ parse receiver }"
73
+ put method.to_s[0]; parse receiver
72
74
 
73
75
  elsif method == :=~
74
- "#{ parse args.first }.test(#{ parse receiver })"
76
+ parse args.first; put '.test('; parse receiver; put ')'
75
77
 
76
78
  elsif method == :!~
77
- "!#{ parse args.first }.test(#{ parse receiver })"
79
+ put '!'; parse args.first; put '.test('; parse receiver; put ')'
78
80
 
79
81
  elsif method == :<< and args.length == 1 and @state == :statement
80
- "#{ parse receiver }.push(#{ parse args.first })"
82
+ parse receiver; put '.push('; parse args.first; put ')'
81
83
 
82
84
  elsif method == :<=>
83
85
  raise NotImplementedError, "use of <=>"
84
86
 
85
87
  elsif OPERATORS.flatten.include?(method) and not LOGICAL.include?(method)
86
- "#{ group_receiver ? group(receiver) : parse(receiver) } #{ method } #{ group_target ? group(target) : parse(target) }"
88
+ (group_receiver ? group(receiver) : parse(receiver))
89
+ put " #{ method } "
90
+ (group_target ? group(target) : parse(target))
87
91
 
88
92
  elsif method =~ /=$/
89
- "#{ parse receiver }#{ '.' if receiver }#{ method.to_s.sub(/=$/, ' =') } #{ parse args.first }"
93
+ parse receiver
94
+ put "#{ '.' if receiver }#{ method.to_s.sub(/=$/, ' =') } "
95
+ parse args.first
90
96
 
91
97
  elsif method == :new
92
98
  if receiver
@@ -120,12 +126,9 @@ module Ruby2JS
120
126
  end
121
127
  end
122
128
 
123
- args = args.map {|a| parse a}.join(', ')
124
-
129
+ put "new "; parse receiver
125
130
  if ast.is_method?
126
- "new #{ parse receiver }(#{ args })"
127
- else
128
- "new #{ parse receiver }"
131
+ put '('; parse_all *args, join: ', '; put ')'
129
132
  end
130
133
  elsif args.length == 1 and args.first.type == :send
131
134
  # accommodation for JavaScript like new syntax w/argument list
@@ -140,35 +143,33 @@ module Ruby2JS
140
143
 
141
144
  elsif method == :raise and receiver == nil
142
145
  if args.length == 1
143
- "throw #{ parse args.first }"
146
+ put 'throw '; parse args.first
144
147
  else
145
- "throw new #{ parse args.first }(#{ parse args[1] })"
148
+ put 'throw new '; parse args.first; put '('; parse args[1]; put ')'
146
149
  end
147
150
 
148
151
  elsif method == :typeof and receiver == nil
149
- "typeof #{ parse args.first }"
152
+ put 'typeof '; parse args.first
150
153
 
151
154
  else
152
155
  if not ast.is_method?
153
156
  if receiver
154
- call = (group_receiver ? group(receiver) : parse(receiver))
155
- "#{ call }.#{ method }"
157
+ (group_receiver ? group(receiver) : parse(receiver))
158
+ put ".#{ method }"
156
159
  else
157
- parse s(:lvasgn, method), @state
160
+ parse ast.updated(:lvasgn, [method]), @state
158
161
  end
159
162
  elsif args.length > 0 and args.any? {|arg| arg.type == :splat}
160
163
  parse s(:send, s(:attr, receiver, method), :apply,
161
164
  (receiver || s(:nil)), s(:array, *args))
162
165
  else
163
- call = (group_receiver ? group(receiver) : parse(receiver))
164
- call = "#{ call }#{ '.' if receiver && method}#{ method }"
165
- args = args.map {|a| parse a}
166
- if args.map {|arg| arg.length+2}.reduce(&:+).to_i < width-10
167
- "#{ call }(#{ args.join(', ') })"
168
- elsif args.length == 1 and args.first.to_s.include? "\n"
169
- "#{ call }(#{ args.join(', ') })"
166
+ (group_receiver ? group(receiver) : parse(receiver))
167
+ put "#{ '.' if receiver && method}#{ method }"
168
+
169
+ if args.length <= 1
170
+ put "("; parse_all *args, join: ', '; put ')'
170
171
  else
171
- "#{ call }(#@nl#{ args.join(",#@ws") }#@nl)"
172
+ compact { puts "("; parse_all *args, join: ",#@ws"; sput ')' }
172
173
  end
173
174
  end
174
175
  end
@@ -10,13 +10,6 @@ module Ruby2JS
10
10
  raise NotImplementedError, "super outside of a method"
11
11
  end
12
12
 
13
- # what to call
14
- if @instance_method.type == :constructor
15
- method = ''
16
- else
17
- method = ".prototype.#{ @instance_method.children[1].to_s.chomp('=') }"
18
- end
19
-
20
13
  # what to pass
21
14
  if @ast.type == :zsuper
22
15
  if @instance_method.type == :method
@@ -28,11 +21,15 @@ module Ruby2JS
28
21
  end
29
22
  end
30
23
 
24
+ parse @class_parent
25
+
26
+ # what to call
27
+ if @instance_method.type != :constructor
28
+ puts ".prototype.#{ @instance_method.children[1].to_s.chomp('=') }"
29
+ end
30
+
31
31
  if args
32
- args = [s(:self), *args].map {|arg| parse arg}.join(', ')
33
- "#{ parse @class_parent }#{ method }.call(#{ args })"
34
- else
35
- "#{ parse @class_parent }#{ method }"
32
+ put '.call('; parse_all s(:self), *args, join: ', '; put ')'
36
33
  end
37
34
  end
38
35
  end
@@ -4,7 +4,7 @@ module Ruby2JS
4
4
  # (sym :sym))
5
5
 
6
6
  handle :sym do |sym|
7
- sym.to_s.inspect
7
+ put sym.to_s.inspect
8
8
  end
9
9
  end
10
10
  end
@@ -6,8 +6,15 @@ module Ruby2JS
6
6
  # (sym :bar))
7
7
 
8
8
  handle :undef do |*syms|
9
- "delete " + syms.
10
- map {|sym| sym.type == :sym ? sym.children.last : parse(sym)}.join(@sep)
9
+ syms.each_with_index do |sym, index|
10
+ put @sep unless index == 0
11
+
12
+ if sym.type == :sym
13
+ put "delete #{sym.children.last}"
14
+ else
15
+ put "delete "; parse sym
16
+ end
17
+ end
11
18
  end
12
19
  end
13
20
  end
@@ -5,7 +5,7 @@ module Ruby2JS
5
5
  # (gvar :$a)
6
6
 
7
7
  handle :lvar, :gvar do |var|
8
- var
8
+ put var
9
9
  end
10
10
  end
11
11
  end
@@ -8,6 +8,7 @@ module Ruby2JS
8
8
  # (int 1))
9
9
 
10
10
  handle :lvasgn, :gvasgn do |name, value=nil|
11
+ state = @state
11
12
  begin
12
13
  if value and value.type == :lvasgn and @state == :statement
13
14
  undecls = []
@@ -25,16 +26,23 @@ module Ruby2JS
25
26
  end
26
27
  end
27
28
 
28
- var = 'var ' unless @vars.include?(name) or @state != :statement
29
+ if state == :statement and @scope and not @vars.include?(name)
30
+ var = 'var '
31
+ end
29
32
 
30
33
  if value
31
-
32
- "#{ var }#{ name } = #{ parse value }"
34
+ put "#{ var }#{ name } = "; parse value
33
35
  else
34
- "#{ var }#{ name }"
36
+ put "#{ var }#{ name }"
35
37
  end
36
38
  ensure
37
- @vars[name] = true
39
+ if @scope
40
+ @vars[name] = true
41
+ elsif state == :statement
42
+ @vars[name] ||= :pending
43
+ else
44
+ @vars[name] ||= :implicit # console, document, ...
45
+ end
38
46
  end
39
47
  end
40
48
  end
@@ -8,7 +8,8 @@ module Ruby2JS
8
8
  handle :while do |condition, block|
9
9
  begin
10
10
  next_token, @next_token = @next_token, :continue
11
- "while (#{ parse condition }) {#@nl#{ scope block }#@nl}"
11
+
12
+ put 'while ('; parse condition; puts ') {'; scope block; sput '}'
12
13
  ensure
13
14
  @next_token = next_token
14
15
  end
@@ -10,7 +10,8 @@ module Ruby2JS
10
10
  block = block.updated(:begin) if block.type == :kwbegin
11
11
  begin
12
12
  next_token, @next_token = @next_token, :continue
13
- "do {#@nl#{ scope block }#@nl} while (#{ parse condition })"
13
+
14
+ puts 'do {'; scope block; sput '} while ('; parse condition; put ')'
14
15
  ensure
15
16
  @next_token = next_token
16
17
  end
@@ -5,11 +5,12 @@ module Ruby2JS
5
5
  # (str 'a'))
6
6
 
7
7
  handle :xstr do |*children|
8
- str = eval children.map{ |child| parse child }.join
8
+ str = eval capture { parse_all *children }
9
+
9
10
  if @binding
10
- @binding.eval(str).to_s
11
+ puts @binding.eval(str).to_s
11
12
  else
12
- eval(str).to_s
13
+ puts eval(str).to_s
13
14
  end
14
15
  end
15
16
  end
@@ -3,14 +3,14 @@ require 'execjs'
3
3
 
4
4
  module Ruby2JS
5
5
  def self.compile(source, options={})
6
- ExecJS.compile(convert(source, options))
6
+ ExecJS.compile(convert(source, options).to_s)
7
7
  end
8
8
 
9
9
  def self.eval(source, options={})
10
- ExecJS.eval(convert(source, options))
10
+ ExecJS.eval(convert(source, options).to_s)
11
11
  end
12
12
 
13
13
  def self.exec(source, options={})
14
- ExecJS.exec(convert(source, options))
14
+ ExecJS.exec(convert(source, options).to_s)
15
15
  end
16
16
  end