ruby2js 3.5.2 → 4.0.1
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 +5 -665
- data/lib/ruby2js.rb +47 -13
- data/lib/ruby2js/converter.rb +9 -3
- data/lib/ruby2js/converter/args.rb +6 -1
- 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 +80 -21
- data/lib/ruby2js/converter/class2.rb +107 -33
- data/lib/ruby2js/converter/def.rb +7 -3
- data/lib/ruby2js/converter/dstr.rb +8 -3
- data/lib/ruby2js/converter/hash.rb +28 -6
- data/lib/ruby2js/converter/hide.rb +13 -0
- data/lib/ruby2js/converter/if.rb +10 -2
- data/lib/ruby2js/converter/import.rb +19 -4
- data/lib/ruby2js/converter/kwbegin.rb +9 -2
- data/lib/ruby2js/converter/literal.rb +14 -2
- data/lib/ruby2js/converter/logical.rb +1 -1
- data/lib/ruby2js/converter/module.rb +41 -4
- data/lib/ruby2js/converter/opasgn.rb +8 -0
- data/lib/ruby2js/converter/return.rb +2 -1
- data/lib/ruby2js/converter/send.rb +73 -8
- data/lib/ruby2js/converter/vasgn.rb +5 -0
- data/lib/ruby2js/converter/xstr.rb +2 -3
- 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 +44 -0
- data/lib/ruby2js/filter/camelCase.rb +6 -3
- data/lib/ruby2js/filter/cjs.rb +2 -0
- data/lib/ruby2js/filter/esm.rb +118 -26
- data/lib/ruby2js/filter/functions.rb +104 -106
- data/lib/ruby2js/filter/{wunderbar.rb → jsx.rb} +29 -7
- data/lib/ruby2js/filter/node.rb +58 -14
- data/lib/ruby2js/filter/nokogiri.rb +12 -12
- data/lib/ruby2js/filter/react.rb +192 -57
- data/lib/ruby2js/filter/require.rb +102 -11
- data/lib/ruby2js/filter/return.rb +13 -1
- data/lib/ruby2js/filter/stimulus.rb +185 -0
- data/lib/ruby2js/jsx.rb +309 -0
- data/lib/ruby2js/namespace.rb +75 -0
- data/lib/ruby2js/rails.rb +15 -9
- data/lib/ruby2js/serializer.rb +3 -1
- data/lib/ruby2js/version.rb +3 -3
- data/ruby2js.gemspec +2 -2
- metadata +17 -9
- data/lib/ruby2js/filter/esm_migration.rb +0 -72
- data/lib/ruby2js/filter/fast-deep-equal.rb +0 -23
@@ -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
|
@@ -5,12 +5,11 @@ module Ruby2JS
|
|
5
5
|
# (str 'a'))
|
6
6
|
|
7
7
|
handle :xstr do |*children|
|
8
|
-
str = eval capture { parse_all(*children) }
|
9
|
-
|
10
8
|
if @binding
|
9
|
+
str = eval capture { parse_all(*children) }
|
11
10
|
puts @binding.eval(str).to_s
|
12
11
|
else
|
13
|
-
|
12
|
+
raise SecurityError.new('Insecure operation, eval without binding option')
|
14
13
|
end
|
15
14
|
end
|
16
15
|
end
|
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
|
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'ruby2js'
|
2
|
+
|
3
|
+
module Ruby2JS
|
4
|
+
module Filter
|
5
|
+
module ActiveFunctions
|
6
|
+
include SEXP
|
7
|
+
|
8
|
+
def on_send(node)
|
9
|
+
target, method, *args = node.children
|
10
|
+
return super unless args.empty?
|
11
|
+
|
12
|
+
if es2015 and method == :blank?
|
13
|
+
create_or_update_import("blank$")
|
14
|
+
process node.updated :send, [nil, "blank$", target]
|
15
|
+
elsif es2015 and method == :present?
|
16
|
+
create_or_update_import("present$")
|
17
|
+
process node.updated :send, [nil, "present$", target]
|
18
|
+
elsif es2015 and method == :presence
|
19
|
+
create_or_update_import("presence$")
|
20
|
+
process node.updated :send, [nil, "presence$", target]
|
21
|
+
else
|
22
|
+
super
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def create_or_update_import(token)
|
29
|
+
af_import = @options[:import_from_skypack] ? "https://cdn.skypack.dev/@ruby2js/active-functions" : "@ruby2js/active-functions"
|
30
|
+
|
31
|
+
if found_node = prepend_list.find {|ast| ast.type == :import && ast.children.first == af_import}
|
32
|
+
unless found_node.children.last.find {|const| const.children.last == token}
|
33
|
+
prepend_list.delete found_node
|
34
|
+
prepend_list << s(:import, found_node.children.first, found_node.children.last.push(s(:const, nil, token)))
|
35
|
+
end
|
36
|
+
else
|
37
|
+
prepend_list << s(:import, af_import, [s(:const, nil, token)])
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
DEFAULTS.push ActiveFunctions
|
43
|
+
end
|
44
|
+
end
|
@@ -9,8 +9,11 @@ module Ruby2JS
|
|
9
9
|
module CamelCase
|
10
10
|
include SEXP
|
11
11
|
|
12
|
-
|
12
|
+
ALLOWLIST = %w{
|
13
13
|
attr_accessor
|
14
|
+
attr_reader
|
15
|
+
attr_writer
|
16
|
+
method_missing
|
14
17
|
}
|
15
18
|
|
16
19
|
CAPS_EXCEPTIONS = {
|
@@ -37,7 +40,7 @@ module Ruby2JS
|
|
37
40
|
node = super
|
38
41
|
return node unless [:send, :csend, :attr].include? node.type
|
39
42
|
|
40
|
-
if node.children[0] == nil and
|
43
|
+
if node.children[0] == nil and ALLOWLIST.include? node.children[1].to_s
|
41
44
|
node
|
42
45
|
elsif node.children[0] && [:ivar, :cvar].include?(node.children[0].type)
|
43
46
|
S(node.type, s(node.children[0].type, camelCase(node.children[0].children[0])),
|
@@ -61,7 +64,7 @@ module Ruby2JS
|
|
61
64
|
def handle_generic_node(node, node_type)
|
62
65
|
return node if node.type != node_type
|
63
66
|
|
64
|
-
if node.children[0] =~ /_.*\w$/
|
67
|
+
if node.children[0] =~ /_.*\w$/ and !ALLOWLIST.include?(node.children[0].to_s)
|
65
68
|
S(node_type , camelCase(node.children[0]), *node.children[1..-1])
|
66
69
|
else
|
67
70
|
node
|
data/lib/ruby2js/filter/cjs.rb
CHANGED
data/lib/ruby2js/filter/esm.rb
CHANGED
@@ -7,30 +7,77 @@ module Ruby2JS
|
|
7
7
|
module ESM
|
8
8
|
include SEXP
|
9
9
|
|
10
|
-
def initialize(*args)
|
11
|
-
super
|
12
|
-
@esm = true # signal for other filters
|
13
|
-
@esm_imports = nil
|
14
|
-
end
|
15
|
-
|
16
10
|
def options=(options)
|
17
11
|
super
|
12
|
+
@esm_autoexports = !@disable_autoexports && options[:autoexports]
|
18
13
|
@esm_autoimports = options[:autoimports]
|
19
|
-
|
14
|
+
@esm_defs = options[:defs] || {}
|
15
|
+
@esm_explicit_tokens = Set.new
|
20
16
|
end
|
21
17
|
|
22
18
|
def process(node)
|
23
|
-
return super
|
24
|
-
@esm_imports = Set.new
|
25
|
-
result = super
|
19
|
+
return super unless @esm_autoexports
|
26
20
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
21
|
+
list = [node]
|
22
|
+
while list.length == 1 and list.first.type == :begin
|
23
|
+
list = list.first.children.dup
|
24
|
+
end
|
25
|
+
|
26
|
+
replaced = []
|
27
|
+
list.map! do |child|
|
28
|
+
replacement = child
|
29
|
+
|
30
|
+
if [:module, :class].include? child.type and
|
31
|
+
child.children.first.type == :const and
|
32
|
+
child.children.first.children.first == nil \
|
33
|
+
then
|
34
|
+
replacement = s(:export, child)
|
35
|
+
elsif child.type == :casgn and child.children.first == nil
|
36
|
+
replacement = s(:export, child)
|
37
|
+
elsif child.type == :def
|
38
|
+
replacement = s(:export, child)
|
39
|
+
end
|
40
|
+
|
41
|
+
if replacement != child
|
42
|
+
replaced << replacement
|
43
|
+
@comments[replacement] = @comments[child] if @comments[child]
|
44
|
+
end
|
45
|
+
|
46
|
+
replacement
|
33
47
|
end
|
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
|
62
|
+
process s(:begin, *list)
|
63
|
+
end
|
64
|
+
|
65
|
+
def on_class(node)
|
66
|
+
@esm_explicit_tokens << node.children.first.children.last
|
67
|
+
|
68
|
+
super
|
69
|
+
end
|
70
|
+
|
71
|
+
def on_def(node)
|
72
|
+
@esm_explicit_tokens << node.children.first
|
73
|
+
|
74
|
+
super
|
75
|
+
end
|
76
|
+
|
77
|
+
def on_lvasgn(node)
|
78
|
+
@esm_explicit_tokens << node.children.first
|
79
|
+
|
80
|
+
super
|
34
81
|
end
|
35
82
|
|
36
83
|
def on_send(node)
|
@@ -46,7 +93,7 @@ module Ruby2JS
|
|
46
93
|
end
|
47
94
|
end
|
48
95
|
|
49
|
-
if args[0].type == :str
|
96
|
+
if args[0].type == :str and args.length == 1
|
50
97
|
# import "file.css"
|
51
98
|
# => import "file.css"
|
52
99
|
s(:import, args[0].children[0])
|
@@ -59,6 +106,8 @@ module Ruby2JS
|
|
59
106
|
args[0].children[2].children[2].type == :str
|
60
107
|
# import name from "file.js"
|
61
108
|
# => import name from "file.js"
|
109
|
+
@esm_explicit_tokens << args[0].children[1]
|
110
|
+
|
62
111
|
s(:import,
|
63
112
|
[args[0].children[2].children[2].children[0]],
|
64
113
|
process(s(:attr, nil, args[0].children[1])))
|
@@ -72,15 +121,25 @@ module Ruby2JS
|
|
72
121
|
# => import Stuff as * from "file.js"
|
73
122
|
# import [ Some, Stuff ], from: "file.js"
|
74
123
|
# => import { Some, Stuff } from "file.js"
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
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
|
128
|
+
@esm_explicit_tokens << args[0].children.last
|
129
|
+
imports << process(args.shift)
|
130
|
+
end
|
131
|
+
|
132
|
+
if args[0].type == :array
|
133
|
+
args[0].children.each {|i| @esm_explicit_tokens << i.children.last}
|
134
|
+
imports << process_all(args.shift.children)
|
135
|
+
end
|
136
|
+
|
137
|
+
s(:import, args[0].children, *imports) unless args[0].nil?
|
79
138
|
end
|
80
139
|
elsif method == :export
|
81
140
|
s(:export, *process_all(args))
|
82
|
-
elsif
|
83
|
-
|
141
|
+
elsif target.nil? and found_import = find_autoimport(method)
|
142
|
+
prepend_list << s(:import, found_import[0], found_import[1])
|
84
143
|
super
|
85
144
|
else
|
86
145
|
super
|
@@ -88,12 +147,45 @@ module Ruby2JS
|
|
88
147
|
end
|
89
148
|
|
90
149
|
def on_const(node)
|
91
|
-
|
92
|
-
|
93
|
-
|
150
|
+
if node.children.first == nil and found_import = find_autoimport(node.children.last)
|
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
|
94
166
|
end
|
167
|
+
|
95
168
|
super
|
96
169
|
end
|
170
|
+
|
171
|
+
def on_export(node)
|
172
|
+
s(:export, *process_all(node.children))
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
private
|
177
|
+
|
178
|
+
def find_autoimport(token)
|
179
|
+
return nil if @esm_autoimports.nil?
|
180
|
+
return nil if @esm_explicit_tokens.include?(token)
|
181
|
+
|
182
|
+
token = camelCase(token) if respond_to?(:camelCase)
|
183
|
+
|
184
|
+
if @esm_autoimports[token]
|
185
|
+
[@esm_autoimports[token], s(:const, nil, token)]
|
186
|
+
elsif found_key = @esm_autoimports.keys.find {|key| key.is_a?(Array) && key.include?(token)}
|
187
|
+
[@esm_autoimports[found_key], found_key.map {|key| s(:const, nil, key)}]
|
188
|
+
end
|
97
189
|
end
|
98
190
|
|
99
191
|
DEFAULTS.push ESM
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'ruby2js'
|
2
|
-
|
2
|
+
|
3
|
+
require 'regexp_parser/scanner'
|
3
4
|
|
4
5
|
module Ruby2JS
|
5
6
|
module Filter
|
@@ -7,7 +8,7 @@ module Ruby2JS
|
|
7
8
|
include SEXP
|
8
9
|
|
9
10
|
# require explicit opt-in to to class => constructor mapping
|
10
|
-
Filter.exclude :class
|
11
|
+
Filter.exclude :class, :call
|
11
12
|
|
12
13
|
VAR_TO_ASSIGN = {
|
13
14
|
lvar: :lvasgn,
|
@@ -23,91 +24,101 @@ module Ruby2JS
|
|
23
24
|
|
24
25
|
def on_send(node)
|
25
26
|
target, method, *args = node.children
|
26
|
-
return super if excluded?(method)
|
27
|
+
return super if excluded?(method) and method != :call
|
27
28
|
|
28
29
|
if [:max, :min].include? method and args.length == 0
|
29
|
-
|
30
|
-
|
31
|
-
|
30
|
+
if target.type == :array
|
31
|
+
process S(:send, s(:const, nil, :Math), node.children[1],
|
32
|
+
*target.children)
|
33
|
+
elsif node.is_method?
|
34
|
+
process S(:send, s(:const, nil, :Math), node.children[1],
|
35
|
+
s(:splat, target))
|
36
|
+
else
|
37
|
+
return super
|
38
|
+
end
|
32
39
|
|
33
|
-
elsif method == :call and target and
|
34
|
-
|
35
|
-
*args)
|
40
|
+
elsif method == :call and target and
|
41
|
+
(%i[ivar cvar].include?(target.type) or not excluded?(:call))
|
36
42
|
|
37
|
-
|
38
|
-
process S(:send, s(:attr, s(:self), :constructor),
|
39
|
-
"_#{target.children.first.to_s[2..-1]}", *args)
|
43
|
+
S(:call, process(target), nil, *process_all(args))
|
40
44
|
|
41
45
|
elsif method == :keys and args.length == 0 and node.is_method?
|
42
46
|
process S(:send, s(:const, nil, :Object), :keys, target)
|
43
47
|
|
44
48
|
elsif method == :[]= and args.length == 3 and
|
45
49
|
args[0].type == :regexp and args[1].type == :int
|
50
|
+
|
46
51
|
index = args[1].children.first
|
47
52
|
|
48
|
-
|
49
|
-
|
50
|
-
|
53
|
+
# identify groups
|
54
|
+
regex = args[0].children.first.children.first
|
55
|
+
tokens = Regexp::Scanner.scan(regex)
|
56
|
+
groups = []
|
57
|
+
stack = []
|
58
|
+
tokens.each do |token|
|
59
|
+
next unless token[0] == :group
|
60
|
+
if token[1] == :capture
|
61
|
+
groups.push token.dup
|
62
|
+
return super if groups.length == index and not stack.empty?
|
63
|
+
stack.push groups.last
|
64
|
+
elsif token[1] == :close
|
65
|
+
stack.pop[-1]=token.last
|
66
|
+
end
|
51
67
|
end
|
68
|
+
group = groups[index-1]
|
52
69
|
|
53
|
-
|
54
|
-
|
55
|
-
|
70
|
+
# rewrite regex
|
71
|
+
prepend = nil
|
72
|
+
append = nil
|
56
73
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
74
|
+
if group[4] < regex.length
|
75
|
+
regex = (regex[0...group[4]] + '(' + regex[group[4]..-1] + ')').
|
76
|
+
sub(/\$\)$/, ')$')
|
77
|
+
append = 2
|
61
78
|
end
|
62
79
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
if parts.first.type == :anchor
|
67
|
-
pre = parts.shift.to_s
|
68
|
-
split -= 1
|
80
|
+
if group[4] - group[3] == 2
|
81
|
+
regex = regex[0...group[3]] + regex[group[4]..-1]
|
82
|
+
append = 1 if append
|
69
83
|
end
|
70
84
|
|
71
|
-
if
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
index += 1
|
77
|
-
end
|
78
|
-
dstr.unshift s(:send, s(:lvar, :match), :[], s(:int, 0))
|
85
|
+
if group[3] > 0
|
86
|
+
regex = ('(' + regex[0...group[3]] + ')' + regex[group[3]..-1]).
|
87
|
+
sub(/^\(\^/, '^(')
|
88
|
+
prepend = 1
|
89
|
+
append += 1 if append
|
79
90
|
end
|
80
91
|
|
92
|
+
regex = process s(:regexp, s(:str, regex), args[0].children.last)
|
81
93
|
|
82
|
-
|
83
|
-
if
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
94
|
+
#
|
95
|
+
if args.last.type == :str
|
96
|
+
str = args.last.children.first.gsub('$', '$$')
|
97
|
+
str = "$#{prepend}#{str}" if prepend
|
98
|
+
str = "#{str}$#{append}" if append
|
99
|
+
expr = s(:send, target, :replace, regex, s(:str, str))
|
100
|
+
else
|
101
|
+
dstr = args.last.type == :dstr ? args.last.children.dup : [args.last]
|
102
|
+
if prepend
|
103
|
+
dstr.unshift s(:send, s(:lvar, :match), :[], s(:int, prepend-1))
|
104
|
+
end
|
105
|
+
if append
|
106
|
+
dstr << s(:send, s(:lvar, :match), :[], s(:int, append-1))
|
92
107
|
end
|
93
|
-
dstr << s(:send, s(:lvar, :match), :[], s(:int, index))
|
94
|
-
end
|
95
|
-
|
96
|
-
rewritten = pre + rewritten + post
|
97
108
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
109
|
+
expr = s(:block,
|
110
|
+
s(:send, target, :replace, regex),
|
111
|
+
s(:args, s(:arg, :match)),
|
112
|
+
process(s(:dstr, *dstr)))
|
113
|
+
end
|
103
114
|
|
104
115
|
if VAR_TO_ASSIGN.keys.include? target.type
|
105
|
-
S(VAR_TO_ASSIGN[target.type], target.children.first,
|
116
|
+
S(VAR_TO_ASSIGN[target.type], target.children.first, expr)
|
106
117
|
elsif target.type == :send
|
107
118
|
if target.children[0] == nil
|
108
|
-
S(:lvasgn, target.children[1],
|
119
|
+
S(:lvasgn, target.children[1], expr)
|
109
120
|
else
|
110
|
-
S(:send, target.children[0], :"#{target.children[1]}=",
|
121
|
+
S(:send, target.children[0], :"#{target.children[1]}=", expr)
|
111
122
|
end
|
112
123
|
else
|
113
124
|
super
|
@@ -116,57 +127,14 @@ module Ruby2JS
|
|
116
127
|
elsif method == :merge
|
117
128
|
args.unshift target
|
118
129
|
|
119
|
-
if
|
120
|
-
|
121
|
-
process S(:hash, *args.map {|arg| s(:kwsplat, arg)})
|
122
|
-
else
|
123
|
-
process S(:send, s(:const, nil, :Object), :assign, s(:hash),
|
124
|
-
*args)
|
125
|
-
end
|
130
|
+
if es2018
|
131
|
+
process S(:hash, *args.map {|arg| s(:kwsplat, arg)})
|
126
132
|
else
|
127
|
-
|
128
|
-
|
129
|
-
s(:send, s(:block, s(:send, nil, :lambda), s(:args),
|
130
|
-
s(:begin, *copy, *args.map {|modname|
|
131
|
-
if modname.type == :hash
|
132
|
-
s(:begin, *modname.children.map {|pair|
|
133
|
-
s(:send, s(:gvar, :$$), :[]=, *pair.children)
|
134
|
-
})
|
135
|
-
else
|
136
|
-
s(:for, s(:lvasgn, :$_), modname,
|
137
|
-
s(:send, s(:gvar, :$$), :[]=,
|
138
|
-
s(:lvar, :$_), s(:send, modname, :[], s(:lvar, :$_))))
|
139
|
-
end
|
140
|
-
}, s(:return, s(:gvar, :$$)))), :[])
|
133
|
+
process S(:assign, s(:hash), *args)
|
141
134
|
end
|
142
135
|
|
143
136
|
elsif method == :merge!
|
144
|
-
|
145
|
-
process S(:send, s(:const, nil, :Object), :assign, target, *args)
|
146
|
-
else
|
147
|
-
copy = []
|
148
|
-
|
149
|
-
unless
|
150
|
-
target.type == :send and target.children.length == 2 and
|
151
|
-
target.children[0] == nil
|
152
|
-
then
|
153
|
-
copy << s(:gvasgn, :$0, target)
|
154
|
-
target = s(:gvar, :$0)
|
155
|
-
end
|
156
|
-
|
157
|
-
s(:send, s(:block, s(:send, nil, :lambda), s(:args),
|
158
|
-
s(:begin, *copy, *args.map {|modname|
|
159
|
-
if modname.type == :hash
|
160
|
-
s(:begin, *modname.children.map {|pair|
|
161
|
-
s(:send, target, :[]=, *pair.children)
|
162
|
-
})
|
163
|
-
else
|
164
|
-
s(:for, s(:lvasgn, :$_), modname,
|
165
|
-
s(:send, target, :[]=,
|
166
|
-
s(:lvar, :$_), s(:send, modname, :[], s(:lvar, :$_))))
|
167
|
-
end
|
168
|
-
}, s(:return, target))), :[])
|
169
|
-
end
|
137
|
+
process S(:assign, target, *args)
|
170
138
|
|
171
139
|
elsif method == :delete and args.length == 1
|
172
140
|
if not target
|
@@ -540,6 +508,25 @@ module Ruby2JS
|
|
540
508
|
elsif method == :floor and args.length == 0
|
541
509
|
process S(:send, s(:const, nil, :Math), :floor, target)
|
542
510
|
|
511
|
+
elsif method == :sum and args.length == 0
|
512
|
+
process S(:send, target, :reduce, s(:block, s(:send, nil, :proc),
|
513
|
+
s(:args, s(:arg, :a), s(:arg, :b)),
|
514
|
+
s(:send, s(:lvar, :a), :+, s(:lvar, :b))), s(:int, 0))
|
515
|
+
|
516
|
+
elsif method == :method_defined? and args.length >= 1
|
517
|
+
if args[1] == s(:false)
|
518
|
+
process S(:send, s(:attr, target, :prototype), :hasOwnProperty, args[0])
|
519
|
+
elsif args.length == 1 or args[1] == s(:true)
|
520
|
+
process S(:in?, args[0], s(:attr, target, :prototype))
|
521
|
+
else
|
522
|
+
process S(:if, args[1], s(:in?, args[0], s(:attr, target, :prototype)),
|
523
|
+
s(:send, s(:attr, target, :prototype), :hasOwnProperty, args[0]))
|
524
|
+
end
|
525
|
+
|
526
|
+
elsif method == :alias_method and args.length == 2
|
527
|
+
process S(:send, s(:attr, target, :prototype), :[]=, args[0],
|
528
|
+
s(:attr, s(:attr, target, :prototype), args[1].children[0]))
|
529
|
+
|
543
530
|
else
|
544
531
|
super
|
545
532
|
end
|
@@ -726,6 +713,10 @@ module Ruby2JS
|
|
726
713
|
s(:return, s(:lvar, node.children[1].children[0].children[0])))),
|
727
714
|
:[], call.children[0]])
|
728
715
|
|
716
|
+
elsif method == :define_method and call.children.length == 3
|
717
|
+
process node.updated(:send, [s(:attr, call.children[0], :prototype), :[]=,
|
718
|
+
call.children[2], s(:deff, nil, *node.children[1..-1])])
|
719
|
+
|
729
720
|
else
|
730
721
|
super
|
731
722
|
end
|
@@ -735,6 +726,12 @@ module Ruby2JS
|
|
735
726
|
name, inheritance, *body = node.children
|
736
727
|
body.compact!
|
737
728
|
|
729
|
+
body.each_with_index do |node, i|
|
730
|
+
if node.type == :send and node.children[0..1] == [nil, :alias_method]
|
731
|
+
body[i] = node.updated(:send, [name, *node.children[1..-1]])
|
732
|
+
end
|
733
|
+
end
|
734
|
+
|
738
735
|
if inheritance == s(:const, nil, :Exception)
|
739
736
|
unless
|
740
737
|
body.any? {|statement| statement.type == :def and
|
@@ -750,7 +747,8 @@ module Ruby2JS
|
|
750
747
|
body = [s(:begin, *body)] if body.length > 1
|
751
748
|
S(:class, name, s(:const, nil, :Error), *body)
|
752
749
|
else
|
753
|
-
|
750
|
+
body = [s(:begin, *body)] if body.length > 1
|
751
|
+
super S(:class, name, inheritance, *body)
|
754
752
|
end
|
755
753
|
end
|
756
754
|
end
|