ruby2js 3.6.1 → 4.0.0
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/README.md +1 -7
- data/lib/ruby2js.rb +32 -9
- data/lib/ruby2js/converter.rb +8 -2
- data/lib/ruby2js/converter/assign.rb +159 -0
- data/lib/ruby2js/converter/begin.rb +7 -2
- data/lib/ruby2js/converter/case.rb +7 -2
- data/lib/ruby2js/converter/class.rb +77 -21
- data/lib/ruby2js/converter/class2.rb +39 -11
- data/lib/ruby2js/converter/def.rb +6 -2
- data/lib/ruby2js/converter/dstr.rb +8 -3
- data/lib/ruby2js/converter/hash.rb +9 -5
- data/lib/ruby2js/converter/hide.rb +13 -0
- data/lib/ruby2js/converter/if.rb +10 -2
- data/lib/ruby2js/converter/import.rb +18 -3
- data/lib/ruby2js/converter/kwbegin.rb +9 -2
- data/lib/ruby2js/converter/literal.rb +2 -2
- data/lib/ruby2js/converter/module.rb +37 -5
- data/lib/ruby2js/converter/opasgn.rb +8 -0
- data/lib/ruby2js/converter/send.rb +41 -2
- data/lib/ruby2js/converter/vasgn.rb +5 -0
- data/lib/ruby2js/demo.rb +53 -0
- data/lib/ruby2js/es2022.rb +5 -0
- data/lib/ruby2js/es2022/strict.rb +3 -0
- data/lib/ruby2js/filter.rb +9 -1
- data/lib/ruby2js/filter/active_functions.rb +1 -0
- data/lib/ruby2js/filter/cjs.rb +2 -0
- data/lib/ruby2js/filter/esm.rb +44 -10
- data/lib/ruby2js/filter/functions.rb +84 -95
- data/lib/ruby2js/filter/{wunderbar.rb → jsx.rb} +29 -7
- data/lib/ruby2js/filter/react.rb +191 -56
- data/lib/ruby2js/filter/require.rb +100 -5
- data/lib/ruby2js/filter/return.rb +13 -1
- data/lib/ruby2js/filter/stimulus.rb +185 -0
- data/lib/ruby2js/jsx.rb +291 -0
- data/lib/ruby2js/namespace.rb +75 -0
- data/lib/ruby2js/version.rb +3 -3
- metadata +12 -4
@@ -8,6 +8,11 @@ module Ruby2JS
|
|
8
8
|
# (int 1))
|
9
9
|
|
10
10
|
handle :lvasgn, :gvasgn do |name, value=nil|
|
11
|
+
if @ast.type == :lvasgn and value
|
12
|
+
receiver = @rbstack.map {|rb| rb[name]}.compact.last
|
13
|
+
return parse s(:attr, receiver, "#{name}=", value) if receiver
|
14
|
+
end
|
15
|
+
|
11
16
|
state = @state
|
12
17
|
begin
|
13
18
|
if value and value.type == :lvasgn and @state == :statement
|
data/lib/ruby2js/demo.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
# helper methods shared between MRI CGI/server and Opal implementations
|
2
|
+
require 'ruby2js'
|
3
|
+
|
4
|
+
module Ruby2JS
|
5
|
+
module Demo
|
6
|
+
def self.parse_autoimports(mappings)
|
7
|
+
autoimports = {}
|
8
|
+
|
9
|
+
mappings = mappings.gsub(/\s+|"|'/, '')
|
10
|
+
|
11
|
+
while mappings and not mappings.empty?
|
12
|
+
if mappings =~ /^(\w+):([^,]+)(,(.*))?$/
|
13
|
+
# symbol: module
|
14
|
+
autoimports[$1.to_sym] = $2
|
15
|
+
mappings = $4
|
16
|
+
elsif mappings =~ /^\[([\w,]+)\]:([^,]+)(,(.*))?$/
|
17
|
+
# [symbol, symbol]: module
|
18
|
+
mname, mappings = $2, $4
|
19
|
+
autoimports[$1.split(/,/).map(&:to_sym)] = mname
|
20
|
+
elsif mappings =~ /^(\w+)(,(.*))?$/
|
21
|
+
# symbol
|
22
|
+
autoimports[$1.to_sym] = $1
|
23
|
+
mappings = $3
|
24
|
+
elsif not mappings.empty?
|
25
|
+
$load_error = "unsupported autoimports mapping: #{mappings}"
|
26
|
+
mappings = ''
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# if nothing is listed, provide a mapping for everything
|
31
|
+
autoimports = proc {|name| name.to_s} if autoimports.empty?
|
32
|
+
|
33
|
+
autoimports
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.parse_defs(mappings)
|
37
|
+
defs = {}
|
38
|
+
|
39
|
+
mappings = mappings.gsub(/\s+|"|'/, '')
|
40
|
+
|
41
|
+
while mappings =~ /^(\w+):\[(:?@?\w+(,:?@?\w+)*)\](,(.*))?$/
|
42
|
+
mappings = $5
|
43
|
+
defs[$1.to_sym] = $2.gsub(':', '').split(',').map(&:to_sym)
|
44
|
+
end
|
45
|
+
|
46
|
+
if mappings and not mappings.empty?
|
47
|
+
$load_error = "unsupported defs: #{mappings}"
|
48
|
+
end
|
49
|
+
|
50
|
+
defs
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
data/lib/ruby2js/filter.rb
CHANGED
@@ -13,6 +13,14 @@ module Ruby2JS
|
|
13
13
|
@@included = nil
|
14
14
|
@@excluded = []
|
15
15
|
|
16
|
+
def self.included_methods
|
17
|
+
@@included&.dup
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.excluded_methods
|
21
|
+
@@excluded&.dup
|
22
|
+
end
|
23
|
+
|
16
24
|
# indicate that the specified methods are not to be processed
|
17
25
|
def self.exclude(*methods)
|
18
26
|
if @@included
|
@@ -52,7 +60,7 @@ module Ruby2JS
|
|
52
60
|
not @included.include? method
|
53
61
|
else
|
54
62
|
return true if @exclude_methods.flatten.include? method
|
55
|
-
@excluded
|
63
|
+
@excluded&.include? method
|
56
64
|
end
|
57
65
|
end
|
58
66
|
|
data/lib/ruby2js/filter/cjs.rb
CHANGED
data/lib/ruby2js/filter/esm.rb
CHANGED
@@ -9,20 +9,21 @@ module Ruby2JS
|
|
9
9
|
|
10
10
|
def options=(options)
|
11
11
|
super
|
12
|
-
@esm_autoexports = options[:autoexports]
|
12
|
+
@esm_autoexports = !@disable_autoexports && options[:autoexports]
|
13
13
|
@esm_autoimports = options[:autoimports]
|
14
|
+
@esm_defs = options[:defs] || {}
|
14
15
|
@esm_explicit_tokens = Set.new
|
15
16
|
end
|
16
17
|
|
17
18
|
def process(node)
|
18
19
|
return super unless @esm_autoexports
|
19
|
-
@esm_autoexports = false
|
20
20
|
|
21
21
|
list = [node]
|
22
22
|
while list.length == 1 and list.first.type == :begin
|
23
23
|
list = list.first.children.dup
|
24
24
|
end
|
25
25
|
|
26
|
+
replaced = []
|
26
27
|
list.map! do |child|
|
27
28
|
replacement = child
|
28
29
|
|
@@ -37,13 +38,27 @@ module Ruby2JS
|
|
37
38
|
replacement = s(:export, child)
|
38
39
|
end
|
39
40
|
|
40
|
-
if replacement != child
|
41
|
-
|
41
|
+
if replacement != child
|
42
|
+
replaced << replacement
|
43
|
+
@comments[replacement] = @comments[child] if @comments[child]
|
42
44
|
end
|
43
45
|
|
44
46
|
replacement
|
45
47
|
end
|
46
48
|
|
49
|
+
if replaced.length == 1 and @esm_autoexports == :default
|
50
|
+
list.map! do |child|
|
51
|
+
if child == replaced.first
|
52
|
+
replacement = s(:export, s(:send, nil, :default, *child.children))
|
53
|
+
@comments[replacement] = @comments[child] if @comments[child]
|
54
|
+
replacement
|
55
|
+
else
|
56
|
+
child
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
@esm_autoexports = false
|
47
62
|
process s(:begin, *list)
|
48
63
|
end
|
49
64
|
|
@@ -78,7 +93,7 @@ module Ruby2JS
|
|
78
93
|
end
|
79
94
|
end
|
80
95
|
|
81
|
-
if args[0].type == :str
|
96
|
+
if args[0].type == :str and args.length == 1
|
82
97
|
# import "file.css"
|
83
98
|
# => import "file.css"
|
84
99
|
s(:import, args[0].children[0])
|
@@ -106,15 +121,20 @@ module Ruby2JS
|
|
106
121
|
# => import Stuff as * from "file.js"
|
107
122
|
# import [ Some, Stuff ], from: "file.js"
|
108
123
|
# => import { Some, Stuff } from "file.js"
|
109
|
-
|
124
|
+
# import Some, [ More, Stuff ], from: "file.js"
|
125
|
+
# => import Some, { More, Stuff } from "file.js"
|
126
|
+
imports = []
|
127
|
+
if %i(const send str).include? args[0].type
|
110
128
|
@esm_explicit_tokens << args[0].children.last
|
111
|
-
process(args
|
112
|
-
|
129
|
+
imports << process(args.shift)
|
130
|
+
end
|
131
|
+
|
132
|
+
if args[0].type == :array
|
113
133
|
args[0].children.each {|i| @esm_explicit_tokens << i.children.last}
|
114
|
-
process_all(args
|
134
|
+
imports << process_all(args.shift.children)
|
115
135
|
end
|
116
136
|
|
117
|
-
s(:import, args[
|
137
|
+
s(:import, args[0].children, *imports) unless args[0].nil?
|
118
138
|
end
|
119
139
|
elsif method == :export
|
120
140
|
s(:export, *process_all(args))
|
@@ -129,6 +149,20 @@ module Ruby2JS
|
|
129
149
|
def on_const(node)
|
130
150
|
if node.children.first == nil and found_import = find_autoimport(node.children.last)
|
131
151
|
prepend_list << s(:import, found_import[0], found_import[1])
|
152
|
+
|
153
|
+
values = @esm_defs[node.children.last]
|
154
|
+
|
155
|
+
if values
|
156
|
+
values = values.map {|value|
|
157
|
+
if value.to_s.start_with? "@"
|
158
|
+
[value.to_s[1..-1].to_sym, s(:self)]
|
159
|
+
else
|
160
|
+
[value.to_sym, s(:autobind, s(:self))]
|
161
|
+
end
|
162
|
+
}.to_h
|
163
|
+
|
164
|
+
@namespace.defineProps values, [node.children.last]
|
165
|
+
end
|
132
166
|
end
|
133
167
|
|
134
168
|
super
|
@@ -1,5 +1,5 @@
|
|
1
1
|
require 'ruby2js'
|
2
|
-
require 'regexp_parser'
|
2
|
+
require 'regexp_parser/scanner'
|
3
3
|
|
4
4
|
module Ruby2JS
|
5
5
|
module Filter
|
@@ -49,71 +49,78 @@ module Ruby2JS
|
|
49
49
|
|
50
50
|
elsif method == :[]= and args.length == 3 and
|
51
51
|
args[0].type == :regexp and args[1].type == :int
|
52
|
+
|
52
53
|
index = args[1].children.first
|
53
54
|
|
54
|
-
|
55
|
-
|
56
|
-
|
55
|
+
# identify groups
|
56
|
+
regex = args[0].children.first.children.first
|
57
|
+
tokens = Regexp::Scanner.scan(regex)
|
58
|
+
groups = []
|
59
|
+
stack = []
|
60
|
+
tokens.each do |token|
|
61
|
+
next unless token[0] == :group
|
62
|
+
if token[1] == :capture
|
63
|
+
groups.push token.dup
|
64
|
+
return super if groups.length == index and not stack.empty?
|
65
|
+
stack.push groups.last
|
66
|
+
elsif token[1] == :close
|
67
|
+
stack.pop[-1]=token.last
|
68
|
+
end
|
57
69
|
end
|
70
|
+
group = groups[index-1]
|
58
71
|
|
59
|
-
|
72
|
+
# rewrite regex
|
73
|
+
prepend = nil
|
74
|
+
append = nil
|
60
75
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
index -= 1
|
66
|
-
rewritten = ''
|
76
|
+
if group[4] < regex.length
|
77
|
+
regex = (regex[0...group[4]] + '(' + regex[group[4]..-1] + ')').
|
78
|
+
sub(/\$\)$/, ')$')
|
79
|
+
append = 2
|
67
80
|
end
|
68
81
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
if parts.first.type == :anchor
|
73
|
-
pre = parts.shift.to_s
|
74
|
-
split -= 1
|
82
|
+
if group[4] - group[3] == 2
|
83
|
+
regex = regex[0...group[3]] + regex[group[4]..-1]
|
84
|
+
append = 1 if append
|
75
85
|
end
|
76
86
|
|
77
|
-
if
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
index += 1
|
83
|
-
end
|
84
|
-
dstr.unshift s(:send, s(:lvar, :match), :[], s(:int, 0))
|
87
|
+
if group[3] > 0
|
88
|
+
regex = ('(' + regex[0...group[3]] + ')' + regex[group[3]..-1]).
|
89
|
+
sub(/^\(\^/, '^(')
|
90
|
+
prepend = 1
|
91
|
+
append += 1 if append
|
85
92
|
end
|
86
93
|
|
94
|
+
regex = process s(:regexp, s(:str, regex), args[0].children.last)
|
87
95
|
|
88
|
-
|
89
|
-
if
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
96
|
+
#
|
97
|
+
if args.last.type == :str
|
98
|
+
str = args.last.children.first.gsub('$', '$$')
|
99
|
+
str = "$#{prepend}#{str}" if prepend
|
100
|
+
str = "#{str}$#{append}" if append
|
101
|
+
expr = s(:send, target, :replace, regex, s(:str, str))
|
102
|
+
else
|
103
|
+
dstr = args.last.type == :dstr ? args.last.children.dup : [args.last]
|
104
|
+
if prepend
|
105
|
+
dstr.unshift s(:send, s(:lvar, :match), :[], s(:int, prepend-1))
|
106
|
+
end
|
107
|
+
if append
|
108
|
+
dstr << s(:send, s(:lvar, :match), :[], s(:int, append-1))
|
98
109
|
end
|
99
|
-
dstr << s(:send, s(:lvar, :match), :[], s(:int, index))
|
100
|
-
end
|
101
|
-
|
102
|
-
rewritten = pre + rewritten + post
|
103
110
|
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
111
|
+
expr = s(:block,
|
112
|
+
s(:send, target, :replace, regex),
|
113
|
+
s(:args, s(:arg, :match)),
|
114
|
+
process(s(:dstr, *dstr)))
|
115
|
+
end
|
109
116
|
|
110
117
|
if VAR_TO_ASSIGN.keys.include? target.type
|
111
|
-
S(VAR_TO_ASSIGN[target.type], target.children.first,
|
118
|
+
S(VAR_TO_ASSIGN[target.type], target.children.first, expr)
|
112
119
|
elsif target.type == :send
|
113
120
|
if target.children[0] == nil
|
114
|
-
S(:lvasgn, target.children[1],
|
121
|
+
S(:lvasgn, target.children[1], expr)
|
115
122
|
else
|
116
|
-
S(:send, target.children[0], :"#{target.children[1]}=",
|
123
|
+
S(:send, target.children[0], :"#{target.children[1]}=", expr)
|
117
124
|
end
|
118
125
|
else
|
119
126
|
super
|
@@ -122,57 +129,14 @@ module Ruby2JS
|
|
122
129
|
elsif method == :merge
|
123
130
|
args.unshift target
|
124
131
|
|
125
|
-
if
|
126
|
-
|
127
|
-
process S(:hash, *args.map {|arg| s(:kwsplat, arg)})
|
128
|
-
else
|
129
|
-
process S(:send, s(:const, nil, :Object), :assign, s(:hash),
|
130
|
-
*args)
|
131
|
-
end
|
132
|
+
if es2018
|
133
|
+
process S(:hash, *args.map {|arg| s(:kwsplat, arg)})
|
132
134
|
else
|
133
|
-
|
134
|
-
|
135
|
-
s(:send, s(:block, s(:send, nil, :lambda), s(:args),
|
136
|
-
s(:begin, *copy, *args.map {|modname|
|
137
|
-
if modname.type == :hash
|
138
|
-
s(:begin, *modname.children.map {|pair|
|
139
|
-
s(:send, s(:gvar, :$$), :[]=, *pair.children)
|
140
|
-
})
|
141
|
-
else
|
142
|
-
s(:for, s(:lvasgn, :$_), modname,
|
143
|
-
s(:send, s(:gvar, :$$), :[]=,
|
144
|
-
s(:lvar, :$_), s(:send, modname, :[], s(:lvar, :$_))))
|
145
|
-
end
|
146
|
-
}, s(:return, s(:gvar, :$$)))), :[])
|
135
|
+
process S(:assign, s(:hash), *args)
|
147
136
|
end
|
148
137
|
|
149
138
|
elsif method == :merge!
|
150
|
-
|
151
|
-
process S(:send, s(:const, nil, :Object), :assign, target, *args)
|
152
|
-
else
|
153
|
-
copy = []
|
154
|
-
|
155
|
-
unless
|
156
|
-
target.type == :send and target.children.length == 2 and
|
157
|
-
target.children[0] == nil
|
158
|
-
then
|
159
|
-
copy << s(:gvasgn, :$0, target)
|
160
|
-
target = s(:gvar, :$0)
|
161
|
-
end
|
162
|
-
|
163
|
-
s(:send, s(:block, s(:send, nil, :lambda), s(:args),
|
164
|
-
s(:begin, *copy, *args.map {|modname|
|
165
|
-
if modname.type == :hash
|
166
|
-
s(:begin, *modname.children.map {|pair|
|
167
|
-
s(:send, target, :[]=, *pair.children)
|
168
|
-
})
|
169
|
-
else
|
170
|
-
s(:for, s(:lvasgn, :$_), modname,
|
171
|
-
s(:send, target, :[]=,
|
172
|
-
s(:lvar, :$_), s(:send, modname, :[], s(:lvar, :$_))))
|
173
|
-
end
|
174
|
-
}, s(:return, target))), :[])
|
175
|
-
end
|
139
|
+
process S(:assign, target, *args)
|
176
140
|
|
177
141
|
elsif method == :delete and args.length == 1
|
178
142
|
if not target
|
@@ -551,6 +515,20 @@ module Ruby2JS
|
|
551
515
|
s(:args, s(:arg, :a), s(:arg, :b)),
|
552
516
|
s(:send, s(:lvar, :a), :+, s(:lvar, :b))), s(:int, 0))
|
553
517
|
|
518
|
+
elsif method == :method_defined? and args.length >= 1
|
519
|
+
if args[1] == s(:false)
|
520
|
+
process S(:send, s(:attr, target, :prototype), :hasOwnProperty, args[0])
|
521
|
+
elsif args.length == 1 or args[1] == s(:true)
|
522
|
+
process S(:in?, args[0], s(:attr, target, :prototype))
|
523
|
+
else
|
524
|
+
process S(:if, args[1], s(:in?, args[0], s(:attr, target, :prototype)),
|
525
|
+
s(:send, s(:attr, target, :prototype), :hasOwnProperty, args[0]))
|
526
|
+
end
|
527
|
+
|
528
|
+
elsif method == :alias_method and args.length == 2
|
529
|
+
process S(:send, s(:attr, target, :prototype), :[]=, args[0],
|
530
|
+
s(:attr, s(:attr, target, :prototype), args[1].children[0]))
|
531
|
+
|
554
532
|
else
|
555
533
|
super
|
556
534
|
end
|
@@ -737,6 +715,10 @@ module Ruby2JS
|
|
737
715
|
s(:return, s(:lvar, node.children[1].children[0].children[0])))),
|
738
716
|
:[], call.children[0]])
|
739
717
|
|
718
|
+
elsif method == :define_method and call.children.length == 3
|
719
|
+
process node.updated(:send, [s(:attr, call.children[0], :prototype), :[]=,
|
720
|
+
call.children[2], s(:deff, nil, *node.children[1..-1])])
|
721
|
+
|
740
722
|
else
|
741
723
|
super
|
742
724
|
end
|
@@ -746,6 +728,12 @@ module Ruby2JS
|
|
746
728
|
name, inheritance, *body = node.children
|
747
729
|
body.compact!
|
748
730
|
|
731
|
+
body.each_with_index do |node, i|
|
732
|
+
if node.type == :send and node.children[0..1] == [nil, :alias_method]
|
733
|
+
body[i] = node.updated(:send, [name, *node.children[1..-1]])
|
734
|
+
end
|
735
|
+
end
|
736
|
+
|
749
737
|
if inheritance == s(:const, nil, :Exception)
|
750
738
|
unless
|
751
739
|
body.any? {|statement| statement.type == :def and
|
@@ -761,7 +749,8 @@ module Ruby2JS
|
|
761
749
|
body = [s(:begin, *body)] if body.length > 1
|
762
750
|
S(:class, name, s(:const, nil, :Error), *body)
|
763
751
|
else
|
764
|
-
|
752
|
+
body = [s(:begin, *body)] if body.length > 1
|
753
|
+
super S(:class, name, inheritance, *body)
|
765
754
|
end
|
766
755
|
end
|
767
756
|
end
|