ruby2js 3.0.12 → 3.0.13

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 33e8a99086fe503dbff4afab72211baf206981e2b0dd68174aa8cc2ea9a1d361
4
- data.tar.gz: 9c86b76630c9c2dbe32032280db32e52b0569ba56ccfcafee0729f8f6d9d351c
3
+ metadata.gz: cdc199c50043c6bf4873bb097b7e92856023ff48baf112aa4c7e9487b749f89b
4
+ data.tar.gz: 3c374a3ca6f1591c61dbc36bf602507c5526aadbf8fbd17c3c6efe7a6e3ca0db
5
5
  SHA512:
6
- metadata.gz: b8a0f54b473fa2494ac736232e8e60487a96923d9cd4df5635329c532726836d15a7b465744e7441016e811b153dcc22993d3e0b7013fa99696c18674f3f66fe
7
- data.tar.gz: c7806d2aefa3449e3f2e07438fdea60a1b222d0bb866f51035ddd95da67a44a009df109ba39bf9ab2da6ba866c8bf4a8fb9652fca5bfea43e5c688307b9141af
6
+ metadata.gz: '02917c6c3e994817a8bbf67aede8dbfa16dbe4d6ee48b7503f763795ddb22ed57b07427179ead407b8036e7c4e36d4fa6848edef7a4951bf39e183f4547e4666'
7
+ data.tar.gz: 496ad88241844101e583205e33f0d7604296801100e1a8870ec2b2f971110f873048d33ed4e7fac4f347bf05d8c545e64867b1b0ff5100dda96c97a98d7f51d6
data/README.md CHANGED
@@ -124,10 +124,10 @@ quite different if `a` is a Hash.
124
124
 
125
125
  One way to resolve this is to change the way indexing operators are evaluated,
126
126
  and to provide a runtime library that adds properties to global JavaScript
127
- objects to handle this. This is the approach that [Opal](http://opalrb.org/)
127
+ objects to handle this. This is the approach that [Opal](http://opalrb.com/)
128
128
  takes. It is a fine approach, with a number of benefits. It also has some
129
129
  notable drawbacks. For example,
130
- [readability](http://opalrb.org/try/#code:a%20%3D%20%22abc%22%3B%20puts%20a[-1])
130
+ [readability](http://opalrb.com/try/#code:a%20%3D%20%22abc%22%3B%20puts%20a[-1])
131
131
  and
132
132
  [compatibility with other frameworks](https://github.com/opal/opal/issues/400).
133
133
 
@@ -229,7 +229,7 @@ the script.
229
229
  * `.find_index` becomes `findIndex`
230
230
  * `.first` becomes `[0]`
231
231
  * `.first(n)` becomes `.slice(0, n)`
232
- * `.gsub` becomes `replace //g`
232
+ * `.gsub` becomes `replace(//g)`
233
233
  * `.include?` becomes `.indexOf() != -1`
234
234
  * `.inspect` becomes `JSON.stringify()`
235
235
  * `.keys` becomes `Object.keys()`
@@ -243,6 +243,7 @@ the script.
243
243
  * `puts` becomes `console.log`
244
244
  * `.replace` becomes `.length = 0; ...push.apply(*)`
245
245
  * `.respond_to?` becomes `right in left`
246
+ * `.scan` becomes `.match(//g)`
246
247
  * `.start_with?` becomes `.substring(0, arg.length) == arg`
247
248
  * `.upto(lim)` becomes `for (var i=num; i<=lim; i+=1)`
248
249
  * `.downto(lim)` becomes `for (var i=num; i>=lim; i-=1)`
@@ -281,6 +282,91 @@ the script.
281
282
 
282
283
  * `.class` becomes `.constructor`
283
284
 
285
+ * <a id="node" * href="https://github.com/rubys/ruby2js/blob/master/spec/node_spec.rb">node</a>
286
+
287
+ * `` `command` `` becomes `child_process.execSync("command", {encoding: "utf8"})`
288
+ * `ARGV` becomes `process.argv.slice(2)`
289
+ * `__dir__` becomes `__dirname`
290
+ * `Dir.chdir` becomes `process.chdir`
291
+ * `Dir.entries` becomes `fs.readdirSync`
292
+ * `Dir.mkdir` becomes `fs.mkdirSync`
293
+ * `Dir.mktmpdir` becomes `fs.mkdtempSync`
294
+ * `Dir.pwd` becomes `process.cwd`
295
+ * `Dir.rmdir` becomes `fs.rmdirSync`
296
+ * `ENV` becomes `process.env`
297
+ * `__FILE__` becomes `__filename`
298
+ * `File.chmod` becomes `fs.chmodSync`
299
+ * `File.chown` becomes `fs.chownSync`
300
+ * `File.cp` becomes `fs.copyFileSync`
301
+ * `File.exist?` becomes `fs.existsSync`
302
+ * `File.lchmod` becomes `fs.lchmodSync`
303
+ * `File.link` becomes `fs.linkSync`
304
+ * `File.ln` becomes `fs.linkSync`
305
+ * `File.lstat` becomes `fs.lstatSync`
306
+ * `File.read` becomes `fs.readFileSync`
307
+ * `File.readlink` becomes `fs.readlinkSync`
308
+ * `File.realpath` becomes `fs.realpathSync`
309
+ * `File.rename` becomes `fs.renameSync`
310
+ * `File.stat` becomes `fs.statSync`
311
+ * `File.symlink` becomes `fs.symlinkSync`
312
+ * `File.truncate` becomes `fs.truncateSync`
313
+ * `File.unlink` becomes `fs.unlinkSync`
314
+ * `FileUtils.cd` becomes `process.chdir`
315
+ * `FileUtils.cp` becomes `fs.copyFileSync`
316
+ * `FileUtils.ln` becomes `fs.linkSync`
317
+ * `FileUtils.ln_s` becomes `fs.symlinkSync`
318
+ * `FileUtils.mkdir` becomes `fs.mkdirSync`
319
+ * `FileUtils.mv` becomes `fs.renameSync`
320
+ * `FileUtils.pwd` becomes `process.cwd`
321
+ * `FileUtils.rm` becomes `fs.unlinkSync`
322
+ * `IO.read` becomes `fs.readFileSync`
323
+ * `IO.write` becomes `fs.writeFileSync`
324
+ * `system` becomes `child_process.execSync(..., {stdio: "inherit"})`
325
+
326
+ * <a id="nokogiri" href="https://github.com/rubys/ruby2js/blob/master/spec/nokogiri.rb">nokogiri</a>
327
+ * `add_child` becomes `appendChild`
328
+ * `add_next_sibling` becomes `node.parentNode.insertBefore(sibling, node.nextSibling)`
329
+ * `add_previous_sibling` becomes `node.parentNode.insertBefore(sibling, node)`
330
+ * `after` becomes `node.parentNode.insertBefore(sibling, node.nextSibling)`
331
+ * `at` becomes `querySelector`
332
+ * `attr` becomes `getAttribute`
333
+ * `attribute` becomes `getAttributeNode`
334
+ * `before` becomes `node.parentNode.insertBefore(sibling, node)`
335
+ * `cdata?` becomes `node.nodeType === Node.CDATA_SECTION_NODE`
336
+ * `children` becomes `childNodes`
337
+ * `comment?` becomes `node.nodeType === Node.COMMENT_NODE`
338
+ * `content` becomes `textContent`
339
+ * `create_element` becomes `createElement`
340
+ * `document` becomes `ownerDocument`
341
+ * `element?` becomes `node.nodeType === Node.ELEMENT_NODE`
342
+ * `fragment?` becomes `node.nodeType === Node.FRAGMENT_NODE`
343
+ * `get_attribute` becomes `getAttribute`
344
+ * `has_attribute` becomes `hasAttribute`
345
+ * `inner_html` becomes `innerHTML`
346
+ * `key?` becomes `hasAttribute`
347
+ * `name` becomes `nextSibling`
348
+ * `next` becomes `nodeName`
349
+ * `next=` becomes `node.parentNode.insertBefore(sibling,node.nextSibling)`
350
+ * `next_element` becomes `nextElement`
351
+ * `next_sibling` becomes `nextSibling`
352
+ * `Nokogiri::HTML5` becomes `new JSDOM().window.document`
353
+ * `Nokogiri::HTML5.parse` becomes `new JSDOM().window.document`
354
+ * `Nokogiri::HTML` becomes `new JSDOM().window.document`
355
+ * `Nokogiri::HTML.parse` becomes `new JSDOM().window.document`
356
+ * `Nokogiri::XML::Node.new` becomes `document.createElement()`
357
+ * `parent` becomes `parentNode`
358
+ * `previous=` becomes `node.parentNode.insertBefore(sibling, node)`
359
+ * `previous_element` becomes `previousElement`
360
+ * `previous_sibling` becomes `previousSibling`
361
+ * `processing_instruction?` becomes `node.nodeType === Node.PROCESSING_INSTRUCTION_NODE`
362
+ * `remove_attribute` becomes `removeAttribute`
363
+ * `root` becomes `documentElement`
364
+ * `search` becomes `querySelectorAll`
365
+ * `set_attribute` becomes `setAttribute`
366
+ * `text?` becomes `node.nodeType === Node.TEXT_NODE`
367
+ * `text` becomes `textContent`
368
+ * `to_html` becomes `outerHTML`
369
+
284
370
  * <a id="rubyjs" href="https://github.com/rubys/ruby2js/blob/master/spec/rubyjs_spec.rb">rubyjs</a>
285
371
  * `.at()` becomes `_a.at()`
286
372
  * `.between?()` becomes `R().between()`
@@ -417,6 +503,14 @@ the script.
417
503
  * maps `assert_operator`, `refute_operator`, `.must_be`, and `.cant_be`
418
504
  calls to `expect`...`toBeGreaterThan()` or `toBeLessThan` calls
419
505
 
506
+ * <a id="cjs" href="https://github.com/rubys/ruby2js/blob/master/spec/cjs">cjs</a>
507
+ * maps `export def f` to `exports.f =`
508
+ * maps `export async def f` to `exports.f = async`
509
+ * maps `export v =` to `exports.v =`
510
+ * maps `export default proc` to `module.exports =`
511
+ * maps `export default async proc` to `module.exports = async`
512
+ * maps `export default` to `module.exports =`
513
+
420
514
  [Wunderbar](https://github.com/rubys/wunderbar) includes additional demos:
421
515
 
422
516
  * [chat](https://github.com/rubys/wunderbar/blob/master/demo/chat.rb),
@@ -480,14 +574,14 @@ Picking a Ruby to JS mapping tool
480
574
 
481
575
  If you simply want to get a job done, and would like a mature and tested
482
576
  framework, and only use one of the many integrations that
483
- [Opal](http://opalrb.org/) provides, then Opal is the way to go right now.
577
+ [Opal](http://opalrb.com/) provides, then Opal is the way to go right now.
484
578
 
485
579
  ruby2js is for those that want to produce JavaScript that looks like it
486
580
  wasn’t machine generated, and want the absolute bare minimum in terms of
487
581
  limitations as to what JavaScript can be produced.
488
582
 
489
- [Try](http://intertwingly.net/projects/ruby2js/all) for yourself.
490
- [Compare](http://opalrb.org/try/#code:).
583
+ [Try](http://intertwingly.net/projects/ruby2js.cgi/all) for yourself.
584
+ [Compare](http://opalrb.com/try/#code:).
491
585
 
492
586
  And, of course, the right solution might be to use
493
587
  [CoffeeScript](http://coffeescript.org/) instead.
@@ -113,6 +113,7 @@ module Ruby2JS
113
113
  def on_prototype(node); on_begin(node); end
114
114
  def on_sendw(node); on_send(node); end
115
115
  def on_undefined?(node); on_defined?(node); end
116
+ def on_nil(node); end
116
117
 
117
118
  # provide a method so filters can call 'super'
118
119
  def on_sym(node); node; end
@@ -195,8 +196,12 @@ module Ruby2JS
195
196
  ruby2js
196
197
  end
197
198
 
198
- def self.parse(source, file=nil)
199
- Parser::CurrentRuby.parse_with_comments(source.encode('utf-8'), file)
199
+ def self.parse(source, file=nil, line=1)
200
+ buffer = Parser::Source::Buffer.new(file, line)
201
+ buffer.source = source.encode('utf-8')
202
+ parser = Parser::CurrentRuby.new
203
+ parser.builder.emit_file_line_as_literals=false
204
+ parser.parse_with_comments(buffer)
200
205
  rescue Parser::SyntaxError => e
201
206
  split = source[0..e.diagnostic.location.begin_pos].split("\n")
202
207
  line, col = split.length, split.last.length
@@ -12,7 +12,7 @@ module Ruby2JS
12
12
 
13
13
  class Converter < Serializer
14
14
  attr_accessor :ast
15
-
15
+
16
16
  LOGICAL = :and, :not, :or
17
17
  OPERATORS = [:[], :[]=], [:not, :!], [:**], [:*, :/, :%], [:+, :-],
18
18
  [:>>, :<<], [:&], [:^, :|], [:<=, :<, :>, :>=], [:==, :!=, :===, :"!=="],
@@ -201,9 +201,11 @@ module Ruby2JS
201
201
  sep = @options[:join].to_s
202
202
  state = @options[:state] || :expression
203
203
 
204
- args.each_with_index do |arg, index|
204
+ index = 0
205
+ args.each do |arg|
205
206
  put sep unless index == 0
206
207
  parse arg, state
208
+ index += 1 unless arg == s(:begin)
207
209
  end
208
210
  end
209
211
 
@@ -288,6 +290,7 @@ require 'ruby2js/converter/def'
288
290
  require 'ruby2js/converter/defs'
289
291
  require 'ruby2js/converter/defined'
290
292
  require 'ruby2js/converter/dstr'
293
+ require 'ruby2js/converter/fileline'
291
294
  require 'ruby2js/converter/for'
292
295
  require 'ruby2js/converter/hash'
293
296
  require 'ruby2js/converter/if'
@@ -126,7 +126,7 @@ module Ruby2JS
126
126
  s(:send, s(:block, s(:send, nil, :lambda), s(:args),
127
127
  s(:begin, *m.children[2..-1].map {|modname|
128
128
  s(:for, s(:lvasgn, :$_), modname,
129
- s(:send, s(:send, name, :prototype), :[]=,
129
+ s(:send, s(:attr, name, :prototype), :[]=,
130
130
  s(:lvar, :$_), s(:send, modname, :[], s(:lvar, :$_))))
131
131
  })), :[])
132
132
  elsif [:private, :protected, :public].include? m.children[1]
@@ -0,0 +1,11 @@
1
+ module Ruby2JS
2
+ class Converter
3
+
4
+ # (true)
5
+ # (false)
6
+
7
+ handle :__FILE__, :__LINE__ do
8
+ put @ast.type.to_s
9
+ end
10
+ end
11
+ end
@@ -8,5 +8,9 @@ module Ruby2JS
8
8
  handle :int, :float, :str do |value|
9
9
  put value.inspect
10
10
  end
11
+
12
+ handle :octal do |value|
13
+ put '0' + value.to_s(8)
14
+ end
11
15
  end
12
16
  end
@@ -124,10 +124,25 @@ module Ruby2JS
124
124
 
125
125
  elsif method == :[]
126
126
  (group_receiver ? group(receiver) : parse(receiver))
127
- put '['; parse_all(*args, join: ', '); put ']'
127
+ if
128
+ args.length == 1 and [:str, :sym].include? args.first.type and
129
+ args.first.children.first.to_s =~ /^[a-zA-Z]\w*$/
130
+ then
131
+ put ".#{args.first.children.first}"
132
+ else
133
+ put '['; parse_all(*args, join: ', '); put ']'
134
+ end
128
135
 
129
136
  elsif method == :[]=
130
- parse receiver; put '['; parse_all(*args[0..-2], join: ', '); put '] = '
137
+ parse receiver
138
+ if
139
+ args.length == 2 and [:str, :sym].include? args.first.type and
140
+ args.first.children.first.to_s =~ /^[a-zA-Z]\w*$/
141
+ then
142
+ put ".#{args.first.children.first} = "
143
+ else
144
+ put '['; parse_all(*args[0..-2], join: ', '); put '] = '
145
+ end
131
146
  parse args[-1]
132
147
 
133
148
  elsif method == :** and not es2016
@@ -245,6 +260,8 @@ module Ruby2JS
245
260
  if receiver
246
261
  (group_receiver ? group(receiver) : parse(receiver))
247
262
  put ".#{ method }"
263
+ elsif ast.type == :attr
264
+ put method
248
265
  else
249
266
  parse ast.updated(:lvasgn, [method]), @state
250
267
  end
@@ -42,15 +42,6 @@ module Ruby2JS
42
42
  end
43
43
  end
44
44
 
45
- # indicate that the specified methods are not to be processed
46
- def self.exclude(*methods)
47
- if @@included
48
- @@included -= methods.flatten
49
- else
50
- @@excluded += methods.flatten
51
- end
52
- end
53
-
54
45
  #
55
46
  # instance level overrides
56
47
  #
@@ -0,0 +1,92 @@
1
+ require 'ruby2js'
2
+
3
+ module Ruby2JS
4
+ module Filter
5
+ module CJS
6
+ include SEXP
7
+
8
+ def on_send(node)
9
+ return super unless node.children[1] == :export
10
+
11
+ if node.children[2].type == :def
12
+ fn = node.children[2]
13
+ node.updated(nil, [
14
+ s(:attr, nil, :exports),
15
+ fn.children[0].to_s + '=',
16
+ s(:block, s(:send, nil, :proc), *process_all(fn.children[1..-1]))
17
+ ])
18
+
19
+ elsif node.children[2].type == :lvasgn
20
+ assign = node.children[2]
21
+ node.updated(nil, [
22
+ s(:attr, nil, :exports),
23
+ assign.children[0].to_s + '=',
24
+ *assign.children[1..-1]
25
+ ])
26
+
27
+ elsif
28
+ node.children[2].type == :send and
29
+ node.children[2].children[0..1] == [nil, :async] and
30
+ node.children[2].children[2].type == :def
31
+ then
32
+ fn = node.children[2].children[2]
33
+ node.updated(nil, [
34
+ s(:attr, nil, :exports),
35
+ fn.children[0].to_s + '=',
36
+ s(:send, nil, :async,
37
+ s(:block, s(:send, nil, :proc),
38
+ *process_all(fn.children[1..-1])))
39
+ ])
40
+
41
+ elsif
42
+ node.children[2].type == :send and
43
+ node.children[2].children[0..1] == [nil, :default]
44
+ then
45
+ node = node.children[2]
46
+
47
+ node.updated(nil, [
48
+ s(:attr, nil, :module),
49
+ :exports=,
50
+ node.children[2]
51
+ ])
52
+
53
+ else
54
+ super
55
+ end
56
+ end
57
+
58
+ def on_block(node)
59
+ child = node.children[0]
60
+ unless child.type == :send and child.children[0..1] == [nil, :export]
61
+ return super
62
+ end
63
+
64
+ send = child.children[2]
65
+ unless send.type == :send and send.children[0..1] == [nil, :default]
66
+ return super
67
+ end
68
+
69
+ if send.children[2] == s(:send, nil, :proc)
70
+ node.updated(:send, [
71
+ s(:attr, nil, :module),
72
+ :exports=,
73
+ s(:block, s(:send, nil, :proc),
74
+ *process_all(node.children[1..-1]))
75
+ ])
76
+ elsif send.children[2] == s(:send, nil, :async, s(:send, nil, :proc))
77
+ node.updated(:send, [
78
+ s(:attr, nil, :module),
79
+ :exports=,
80
+ s(:send, nil, :async,
81
+ s(:block, s(:send, nil, :proc),
82
+ *process_all(node.children[1..-1])))
83
+ ])
84
+ else
85
+ super
86
+ end
87
+ end
88
+ end
89
+
90
+ DEFAULTS.push CJS
91
+ end
92
+ end
@@ -103,6 +103,33 @@ module Ruby2JS
103
103
  super
104
104
  end
105
105
 
106
+ elsif method == :scan and args.length == 1
107
+ arg = args.first
108
+ if arg.type == :str
109
+ arg = arg.updated(:regexp,
110
+ [s(:str, Regexp.escape(arg.children.first)), s(:regopt)])
111
+ end
112
+
113
+ pattern = arg.children.first.children.first
114
+ pattern = pattern.gsub(/\\./, '').gsub(/\[.*\]/, '')
115
+
116
+ if arg.type == :regexp
117
+ gpattern = arg.updated(:regexp, [*arg.children[0...-1],
118
+ s(:regopt, :g, *arg.children.last)])
119
+ else
120
+ super
121
+ end
122
+
123
+ if pattern.include? '('
124
+ s(:block, s(:send,
125
+ s(:send, process(target), :match, gpattern), :map),
126
+ s(:args, s(:arg, :s)),
127
+ s(:return, s(:send, s(:send, s(:lvar, :s), :match, arg),
128
+ :slice, s(:int, 1))))
129
+ else
130
+ S(:send, process(target), :match, gpattern)
131
+ end
132
+
106
133
  elsif method == :gsub and args.length == 2
107
134
  before, after = args
108
135
  if before.type == :regexp
@@ -238,7 +265,7 @@ module Ruby2JS
238
265
 
239
266
  elsif index.type == :regexp
240
267
  process S(:send,
241
- s(:or, S(:send, target, :match, index), s(:array)),
268
+ s(:or, S(:send, process(target), :match, index), s(:array)),
242
269
  :[], args[1] || s(:int, 0))
243
270
 
244
271
  elsif node.children.length != 3
@@ -249,21 +276,27 @@ module Ruby2JS
249
276
 
250
277
  elsif index.type == :erange
251
278
  start, finish = index.children
252
- process S(:send, target, :slice, i.(start), i.(finish))
279
+ if finish.type == :int
280
+ process S(:send, target, :slice, i.(start), finish)
281
+ else
282
+ process S(:send, target, :slice, i.(start), i.(finish))
283
+ end
253
284
 
254
285
  elsif index.type == :irange
255
286
  start, finish = index.children
256
- start = i.(start)
257
287
  if finish.type == :int
258
- if finish.children.first == -1
259
- finish = S(:attr, target, :length)
260
- else
261
- finish = i.(S(:int, finish.children.first+1))
262
- end
288
+ final = S(:int, finish.children.first+1)
289
+ else
290
+ final = S(:send, finish, :+, s(:int, 1))
291
+ end
292
+
293
+ # No need for the last argument if it's -1
294
+ # This means take all to the end of array
295
+ if finish.children.first == -1
296
+ process S(:send, target, :slice, start)
263
297
  else
264
- finish = S(:send, finish, :+, s(:int, 1))
298
+ process S(:send, target, :slice, start, final)
265
299
  end
266
- process S(:send, target, :slice, start, finish)
267
300
 
268
301
  else
269
302
  super
@@ -0,0 +1,341 @@
1
+ require 'ruby2js'
2
+ require 'set'
3
+
4
+ module Ruby2JS
5
+ module Filter
6
+ module Node
7
+ include SEXP
8
+ extend SEXP
9
+
10
+ NODE_SETUP = {
11
+ child_process: s(:casgn, nil, :child_process,
12
+ s(:send, nil, :require, s(:str, "child_process"))),
13
+ fs: s(:casgn, nil, :fs, s(:send, nil, :require, s(:str, "fs"))),
14
+ ARGV: s(:lvasgn, :ARGV, s(:send, s(:attr,
15
+ s(:attr, nil, :process), :argv), :slice, s(:int, 2)))
16
+ }
17
+
18
+ def initialize(*args)
19
+ @node_setup = nil
20
+ super
21
+ end
22
+
23
+ def process(node)
24
+ return super if @node_setup
25
+ @node_setup = Set.new
26
+ result = super
27
+
28
+ if @node_setup.empty?
29
+ result
30
+ else
31
+ s(:begin, *@node_setup.to_a.map {|token| NODE_SETUP[token]},
32
+ result)
33
+ end
34
+ end
35
+
36
+ def on_send(node)
37
+ target, method, *args = node.children
38
+
39
+ if target == nil
40
+ if method == :__dir__ and args.length == 0
41
+ S(:attr, nil, :__dirname)
42
+
43
+ elsif method == :exit and args.length <= 1
44
+ s(:send, s(:attr, nil, :process), :exit, *process_all(args));
45
+
46
+ elsif method == :system
47
+ @node_setup << :child_process
48
+
49
+ if args.length == 1
50
+ s(:send, s(:attr, nil, :child_process), :execSync,
51
+ process(args.first),
52
+ s(:hash, s(:pair, s(:sym, :stdio), s(:str, 'inherit'))))
53
+ else
54
+ s(:send, s(:attr, nil, :child_process), :execFileSync,
55
+ process(args.first), s(:array, *process_all(args[1..-1])),
56
+ s(:hash, s(:pair, s(:sym, :stdio), s(:str, 'inherit'))))
57
+ end
58
+
59
+ elsif
60
+ method == :require and args.length == 1 and
61
+ args.first.type == :str and
62
+ %w(fileutils tmpdir).include? args.first.children.first
63
+ then
64
+ s(:begin)
65
+
66
+ else
67
+ super
68
+ end
69
+
70
+ elsif
71
+ [:File, :IO].include? target.children.last and
72
+ target.type == :const and target.children.first == nil
73
+ then
74
+ if method == :read and args.length == 1
75
+ @node_setup << :fs
76
+ s(:send, s(:attr, nil, :fs), :readFileSync, *process_all(args),
77
+ s(:str, 'utf8'))
78
+
79
+ elsif method == :write and args.length == 2
80
+ @node_setup << :fs
81
+ S(:send, s(:attr, nil, :fs), :writeFileSync, *process_all(args))
82
+
83
+ elsif target.children.last == :IO
84
+ super
85
+
86
+ elsif [:exist?, :exists?].include? method and args.length == 1
87
+ @node_setup << :fs
88
+ S(:send, s(:attr, nil, :fs), :existsSync, process(args.first))
89
+
90
+ elsif method == :readlink and args.length == 1
91
+ @node_setup << :fs
92
+ S(:send, s(:attr, nil, :fs), :readlinkSync, process(args.first))
93
+
94
+ elsif method == :realpath and args.length == 1
95
+ @node_setup << :fs
96
+ S(:send, s(:attr, nil, :fs), :realpathSync, process(args.first))
97
+
98
+ elsif method == :rename and args.length == 2
99
+ @node_setup << :fs
100
+ S(:send, s(:attr, nil, :fs), :renameSync, *process_all(args))
101
+
102
+ elsif
103
+ [:chmod, :lchmod].include? method and
104
+ args.length > 1 and args.first.type == :int
105
+ then
106
+ @node_setup << :fs
107
+
108
+ S(:begin, *args[1..-1].map{|file|
109
+ S(:send, s(:attr, nil, :fs), method.to_s + 'Sync', process(file),
110
+ s(:octal, *args.first.children))
111
+ })
112
+
113
+ elsif
114
+ [:chown, :lchown].include? method and args.length > 2 and
115
+ args[0].type == :int and args[1].type == :int
116
+ then
117
+ @node_setup << :fs
118
+
119
+ S(:begin, *args[2..-1].map{|file|
120
+ s(:send, s(:attr, nil, :fs), method.to_s + 'Sync', process(file),
121
+ *process_all(args[0..1]))
122
+ })
123
+
124
+ elsif [:ln, :link].include? method and args.length == 2
125
+ @node_setup << :fs
126
+ s(:send, s(:attr, nil, :fs), :linkSync, *process_all(args))
127
+
128
+ elsif method == :symlink and args.length == 2
129
+ @node_setup << :fs
130
+ s(:send, s(:attr, nil, :fs), :symlinkSync, *process_all(args))
131
+
132
+ elsif method == :truncate and args.length == 2
133
+ @node_setup << :fs
134
+ s(:send, s(:attr, nil, :fs), :truncateSync, *process_all(args))
135
+
136
+ elsif [:stat, :lstat].include? method and args.length == 1
137
+ @node_setup << :fs
138
+ s(:send, s(:attr, nil, :fs), method.to_s + 'Sync',
139
+ process(args.first))
140
+
141
+ elsif method == :unlink and args.length == 1
142
+ @node_setup << :fs
143
+ S(:begin, *args.map{|file|
144
+ S(:send, s(:attr, nil, :fs), :unlinkSync, process(file))
145
+ })
146
+
147
+ else
148
+ super
149
+ end
150
+
151
+ elsif
152
+ target.children.last == :FileUtils and
153
+ target.type == :const and target.children.first == nil
154
+ then
155
+
156
+ list = proc do |arg|
157
+ if arg.type == :array
158
+ arg.children
159
+ else
160
+ [arg]
161
+ end
162
+ end
163
+
164
+ if [:cp, :copy].include? method and args.length == 2
165
+ @node_setup << :fs
166
+ s(:send, s(:attr, nil, :fs), :copyFileSync, *process_all(args))
167
+
168
+ elsif [:mv, :move].include? method and args.length == 2
169
+ @node_setup << :fs
170
+ S(:send, s(:attr, nil, :fs), :renameSync, *process_all(args))
171
+
172
+ elsif method == :mkdir and args.length == 1
173
+ @node_setup << :fs
174
+ S(:begin, *list[args.last].map {|file|
175
+ s(:send, s(:attr, nil, :fs), :mkdirSync, process(file))
176
+ })
177
+
178
+ elsif method == :cd and args.length == 1
179
+ S(:send, s(:attr, nil, :process), :chdir, *process_all(args))
180
+
181
+ elsif method == :pwd and args.length == 0
182
+ s(:send, s(:attr, nil, :process), :cwd)
183
+
184
+ elsif method == :rmdir and args.length == 1
185
+ @node_setup << :fs
186
+ S(:begin, *list[args.last].map {|file|
187
+ s(:send, s(:attr, nil, :fs), :rmdirSync, process(file))
188
+ })
189
+
190
+ elsif method == :ln and args.length == 2
191
+ @node_setup << :fs
192
+ s(:send, s(:attr, nil, :fs), :linkSync, *process_all(args))
193
+
194
+ elsif method == :ln_s and args.length == 2
195
+ @node_setup << :fs
196
+ s(:send, s(:attr, nil, :fs), :symlinkSync, *process_all(args))
197
+
198
+ elsif method == :rm and args.length == 1
199
+ @node_setup << :fs
200
+ S(:begin, *list[args.last].map {|file|
201
+ s(:send, s(:attr, nil, :fs), :unlinkSync, process(file))
202
+ })
203
+
204
+ elsif
205
+ method == :chmod and args.length == 2 and args.first.type == :int
206
+ then
207
+ @node_setup << :fs
208
+
209
+ S(:begin, *list[args.last].map {|file|
210
+ S(:send, s(:attr, nil, :fs), method.to_s + 'Sync', process(file),
211
+ s(:octal, *args.first.children))
212
+ })
213
+
214
+ elsif
215
+ method == :chown and args.length == 3 and
216
+ args[0].type == :int and args[1].type == :int
217
+ then
218
+ @node_setup << :fs
219
+
220
+ S(:begin, *list[args.last].map {|file|
221
+ s(:send, s(:attr, nil, :fs), method.to_s + 'Sync', process(file),
222
+ *process_all(args[0..1]))})
223
+
224
+ elsif method == :touch
225
+ @node_setup << :fs
226
+
227
+ S(:begin, *list[args.first].map {|file|
228
+ S(:send, s(:attr, nil, :fs), :closeSync,
229
+ s(:send, s(:attr, nil, :fs), :openSync, file,
230
+ s(:str, "w")))})
231
+
232
+ else
233
+ super
234
+ end
235
+
236
+ elsif
237
+ target.type == :const and target.children.first == nil and
238
+ target.children.last == :Dir
239
+ then
240
+ if method == :chdir and args.length == 1
241
+ S(:send, s(:attr, nil, :process), :chdir, *process_all(args))
242
+ elsif method == :pwd and args.length == 0
243
+ s(:send, s(:attr, nil, :process), :cwd)
244
+ elsif method == :entries
245
+ @node_setup << :fs
246
+ s(:send, s(:attr, nil, :fs), :readdirSync, *process_all(args))
247
+ elsif method == :mkdir and args.length == 1
248
+ @node_setup << :fs
249
+ s(:send, s(:attr, nil, :fs), :mkdirSync, process(args.first))
250
+ elsif method == :rmdir and args.length == 1
251
+ @node_setup << :fs
252
+ s(:send, s(:attr, nil, :fs), :rmdirSync, process(args.first))
253
+ elsif method == :mktmpdir and args.length <=1
254
+ @node_setup << :fs
255
+ if args.length == 0
256
+ prefix = s(:str, 'd')
257
+ elsif args.first.type == :array
258
+ prefix = args.first.children.first
259
+ else
260
+ prefix = args.first
261
+ end
262
+
263
+ s(:send, s(:attr, nil, :fs), :mkdtempSync, process(prefix))
264
+ else
265
+ super
266
+ end
267
+
268
+ else
269
+ super
270
+ end
271
+ end
272
+
273
+ def on_block(node)
274
+ call = node.children.first
275
+ target, method, *args = call.children
276
+
277
+ if
278
+ method == :chdir and args.length == 1 and
279
+ target.children.last == :Dir and
280
+ target.type == :const and target.children.first == nil
281
+ then
282
+ s(:begin,
283
+ s(:gvasgn, :$oldwd, s(:send, s(:attr, nil, :process), :cwd)),
284
+ s(:kwbegin, s(:ensure,
285
+ s(:begin, process(call), process(node.children.last)),
286
+ s(:send, s(:attr, nil, :process), :chdir, s(:gvar, :$oldwd)))))
287
+ else
288
+ super
289
+ end
290
+ end
291
+
292
+ def on_const(node)
293
+ if node.children == [nil, :ARGV]
294
+ @node_setup << :ARGV
295
+ super
296
+ elsif node.children == [nil, :ENV]
297
+ S(:attr, s(:attr, nil, :process), :env)
298
+ elsif node.children == [nil, :STDIN]
299
+ S(:attr, s(:attr, nil, :process), :stdin)
300
+ elsif node.children == [nil, :STDOUT]
301
+ S(:attr, s(:attr, nil, :process), :stdout)
302
+ elsif node.children == [nil, :STDERR]
303
+ S(:attr, s(:attr, nil, :process), :stderr)
304
+ else
305
+ super
306
+ end
307
+ end
308
+
309
+ def on_gvar(node)
310
+ if node.children == [:$stdin]
311
+ S(:attr, s(:attr, nil, :process), :stdin)
312
+ elsif node.children == [:$stdout]
313
+ S(:attr, s(:attr, nil, :process), :stdout)
314
+ elsif node.children == [:$stderr]
315
+ S(:attr, s(:attr, nil, :process), :stderr)
316
+ else
317
+ super
318
+ end
319
+ end
320
+
321
+ def on_xstr(node)
322
+ @node_setup << :child_process
323
+
324
+ children = node.children.dup
325
+ command = children.shift
326
+ while children.length > 0
327
+ command = s(:send, accumulator, :+, children.shift)
328
+ end
329
+
330
+ s(:send, s(:attr, nil, :child_process), :execSync, command,
331
+ s(:hash, s(:pair, s(:sym, :encoding), s(:str, 'utf8'))))
332
+ end
333
+
334
+ def on___FILE__(node)
335
+ s(:attr, nil, :__filename)
336
+ end
337
+ end
338
+
339
+ DEFAULTS.push Node
340
+ end
341
+ end
@@ -0,0 +1,261 @@
1
+ require 'ruby2js'
2
+ require 'set'
3
+
4
+ module Ruby2JS
5
+ module Filter
6
+ module Nokogiri
7
+ include SEXP
8
+ extend SEXP
9
+
10
+ NOKOGIRI_SETUP = {
11
+ jsdom: s(:casgn, nil, :JSDOM,
12
+ s(:attr, s(:send, nil, :require, s(:str, "jsdom")), :JSDOM))
13
+ }
14
+
15
+ def initialize(*args)
16
+ @nokogiri_setup = nil
17
+ super
18
+ end
19
+
20
+ def process(node)
21
+ return super if @nokogiri_setup
22
+ @nokogiri_setup = Set.new
23
+ result = super
24
+
25
+ if @nokogiri_setup.empty?
26
+ result
27
+ else
28
+ s(:begin,
29
+ *@nokogiri_setup.to_a.map {|token| NOKOGIRI_SETUP[token]},
30
+ result)
31
+ end
32
+ end
33
+
34
+ def on_send(node)
35
+ target, method, *args = node.children
36
+ return super if excluded?(method)
37
+
38
+ if target == nil
39
+ if
40
+ method == :require and args.length == 1 and
41
+ args.first.type == :str and
42
+ %w(nokogiri nokogumbo).include? args.first.children.first
43
+ then
44
+ s(:begin)
45
+
46
+ else
47
+ super
48
+ end
49
+
50
+ elsif
51
+ [:HTML, :HTML5].include? method and
52
+ target == s(:const, nil, :Nokogiri)
53
+ then
54
+ @nokogiri_setup << :jsdom
55
+ S(:attr, s(:attr, s(:send, s(:const, nil, :JSDOM), :new,
56
+ *process_all(args)), :window), :document)
57
+
58
+ elsif
59
+ method == :parse and
60
+ target.type == :const and
61
+ target.children.first == s(:const, nil, :Nokogiri) and
62
+ [:HTML, :HTML5].include? target.children.last
63
+ then
64
+ @nokogiri_setup << :jsdom
65
+ S(:attr, s(:attr, s(:send, s(:const, nil, :JSDOM), :new,
66
+ *process_all(args)), :window), :document)
67
+
68
+ elsif
69
+ method == :at and
70
+ args.length == 1 and args.first.type == :str
71
+ then
72
+ S(:send, target, :querySelector, process(args.first))
73
+
74
+ elsif
75
+ method == :search and
76
+ args.length == 1 and args.first.type == :str
77
+ then
78
+ S(:send, target, :querySelectorAll, process(args.first))
79
+
80
+ elsif method === :parent and args.length == 0
81
+ S(:attr, target, :parentNode)
82
+
83
+ elsif method === :name and args.length == 0
84
+ S(:attr, target, :nodeName)
85
+
86
+ elsif [:text, :content].include? method and args.length == 0
87
+ S(:attr, target, :textContent)
88
+
89
+ elsif method == :content= and args.length == 1
90
+ S(:send, target, :textContent=, *process_all(args))
91
+
92
+ elsif method === :inner_html and args.length == 0
93
+ S(:attr, target, :innerHTML)
94
+
95
+ elsif method == :inner_html= and args.length == 1
96
+ S(:send, target, :innerHTML=, *process_all(args))
97
+
98
+ elsif method === :to_html and args.length == 0
99
+ S(:attr, target, :outerHTML)
100
+
101
+ elsif
102
+ [:attr, :get_attribute].include? method and
103
+ args.length == 1 and args.first.type == :str
104
+ then
105
+ S(:send, target, :getAttribute, process(args.first))
106
+
107
+ elsif
108
+ [:key?, :has_attribute].include? method and
109
+ args.length == 1 and args.first.type == :str
110
+ then
111
+ S(:send, target, :hasAttribute, process(args.first))
112
+
113
+ elsif
114
+ method == :set_attribute and
115
+ args.length == 2 and args.first.type == :str
116
+ then
117
+ S(:send, target, :setAttribute, *process_all(args))
118
+
119
+ elsif
120
+ method == :attribute and
121
+ args.length == 1 and args.first.type == :str
122
+ then
123
+ S(:send, target, :getAttributeNode, *process_all(args))
124
+
125
+ elsif method == :remove_attribute and args.length == 1
126
+ S(:send, target, :removeAttribute, process(args.first))
127
+
128
+ elsif method == :attribute_nodes and args.length == 0
129
+ S(:attr, target, :attributes)
130
+
131
+ elsif
132
+ method == :new and args.length == 2 and
133
+ target == s(:const, s(:const, s(:const, nil, :Nokogiri), :XML), :Node)
134
+ then
135
+ S(:send, process(args.last), :createElement, process(args.first))
136
+
137
+ elsif method == :create_element
138
+ create = S(:send, target, :createElement, process(args.first))
139
+ if args.length == 1
140
+ create
141
+ elsif true
142
+ init = []
143
+ args[1..-1].each do |arg|
144
+ if arg.type == :hash
145
+ init += arg.children.map do |pair|
146
+ s(:send, s(:gvar, :$_), :setAttribute,
147
+ *process_all(pair.children))
148
+ end
149
+ elsif arg.type == :str
150
+ init << s(:send, s(:gvar, :$_), :content=, process(arg))
151
+ else
152
+ return super
153
+ end
154
+ end
155
+
156
+ S(:send, s(:block, s(:send, nil, :proc), s(:args),
157
+ s(:begin, s(:gvasgn, :$_, create), *init,
158
+ s(:return, s(:gvar, :$_)))), :[])
159
+ else
160
+ super
161
+ end
162
+
163
+ elsif method == :create_text and args.length == 1
164
+ create = S(:send, target, :createTextNode, process(args.first))
165
+
166
+ elsif method == :create_comment and args.length == 1
167
+ create = S(:send, target, :createComment, process(args.first))
168
+
169
+ elsif method == :create_cdata and args.length == 1
170
+ create = S(:send, target, :createCDATASection, process(args.first))
171
+
172
+ elsif method == :add_child and args.length == 1
173
+ S(:send, target, :appendChild, process(args.first))
174
+
175
+ elsif
176
+ [:add_next_sibling, :next=, :after].include? method and
177
+ args.length == 1
178
+ then
179
+ S(:send, s(:attr, target, :parentNode), :insertBefore,
180
+ process(args.first), s(:attr, target, :nextSibling))
181
+
182
+ elsif
183
+ [:add_previous_sibling, :previous=, :before].include? method and
184
+ args.length == 1
185
+ then
186
+ S(:send, s(:attr, target, :parentNode), :insertBefore,
187
+ process(args.first), target)
188
+
189
+ elsif method == :prepend_child and args.length == 1
190
+ S(:send, target, :insertBefore,
191
+ process(args.first), s(:attr, target, :firstChild))
192
+
193
+ elsif method == :next_element and args.length == 0
194
+ S(:attr, target, :nextElement)
195
+
196
+ elsif [:next, :next_sibling].include? method and args.length == 0
197
+ S(:attr, target, :nextSibling)
198
+
199
+ elsif method == :previous_element and args.length == 0
200
+ S(:attr, target, :previousElement)
201
+
202
+ elsif
203
+ [:previous, :previous_sibling].include? method and args.length == 0
204
+ then
205
+ S(:attr, target, :previousSibling)
206
+
207
+ elsif method == :cdata? and args.length == 0
208
+ S(:send, s(:attr, target, :nodeType), :===,
209
+ s(:attr, s(:const, nil, :Node), :CDATA_SECTION_NODE))
210
+
211
+ elsif method == :comment? and args.length == 0
212
+ S(:send, s(:attr, target, :nodeType), :===,
213
+ s(:attr, s(:const, nil, :Node), :COMMENT_NODE))
214
+
215
+ elsif method == :element? and args.length == 0
216
+ S(:send, s(:attr, target, :nodeType), :===,
217
+ s(:attr, s(:const, nil, :Node), :ELEMENT_NODE))
218
+
219
+ elsif method == :fragment? and args.length == 0
220
+ S(:send, s(:attr, target, :nodeType), :===,
221
+ s(:attr, s(:const, nil, :Node), :DOCUMENT_FRAGMENT_NODE))
222
+
223
+ elsif method == :processing_instruction? and args.length == 0
224
+ S(:send, s(:attr, target, :nodeType), :===,
225
+ s(:attr, s(:const, nil, :Node), :PROCESSING_INSTRUCTION_NODE))
226
+
227
+ elsif method == :text? and args.length == 0
228
+ S(:send, s(:attr, target, :nodeType), :===,
229
+ s(:attr, s(:const, nil, :Node), :TEXT_NODE))
230
+
231
+ elsif method == :children and args.length == 0
232
+ S(:attr, target, :childNodes)
233
+
234
+ elsif method == :first_element_child and args.length == 0
235
+ S(:attr, target, :firstElementChild)
236
+
237
+ elsif method == :last_element_child and args.length == 0
238
+ S(:attr, target, :lastElementChild)
239
+
240
+ elsif method == :replace and args.length == 1
241
+ S(:send, target, :replaceWith, process(args.first))
242
+
243
+ elsif [:remove, :unlink].include? method and args.length == 0
244
+ S(:send, target, :remove)
245
+
246
+ elsif method == :root and args.length == 0
247
+ S(:attr, target, :documentElement)
248
+
249
+ elsif method == :document and args.length == 0
250
+ S(:attr, target, :ownerDocument)
251
+
252
+ else
253
+ return super
254
+
255
+ end
256
+ end
257
+ end
258
+
259
+ DEFAULTS.push Nokogiri
260
+ end
261
+ end
@@ -216,6 +216,8 @@ module Ruby2JS
216
216
  s(:attr, nil, :undefined))
217
217
  end
218
218
 
219
+ next if pairs.empty? and @comments[statement].empty?
220
+
219
221
  block = s(:return, s(:hash, *pairs))
220
222
  else
221
223
  # general case: build up a hash incrementally
@@ -2,7 +2,7 @@ module Ruby2JS
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 3
4
4
  MINOR = 0
5
- TINY = 12
5
+ TINY = 13
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby2js
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.12
4
+ version: 3.0.13
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sam Ruby
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-08-16 00:00:00.000000000 Z
11
+ date: 2018-11-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: parser
@@ -56,6 +56,7 @@ files:
56
56
  - lib/ruby2js/converter/defined.rb
57
57
  - lib/ruby2js/converter/defs.rb
58
58
  - lib/ruby2js/converter/dstr.rb
59
+ - lib/ruby2js/converter/fileline.rb
59
60
  - lib/ruby2js/converter/for.rb
60
61
  - lib/ruby2js/converter/hash.rb
61
62
  - lib/ruby2js/converter/if.rb
@@ -95,9 +96,12 @@ files:
95
96
  - lib/ruby2js/execjs.rb
96
97
  - lib/ruby2js/filter.rb
97
98
  - lib/ruby2js/filter/camelCase.rb
99
+ - lib/ruby2js/filter/cjs.rb
98
100
  - lib/ruby2js/filter/functions.rb
99
101
  - lib/ruby2js/filter/jquery.rb
100
102
  - lib/ruby2js/filter/minitest-jasmine.rb
103
+ - lib/ruby2js/filter/node.rb
104
+ - lib/ruby2js/filter/nokogiri.rb
101
105
  - lib/ruby2js/filter/react.rb
102
106
  - lib/ruby2js/filter/require.rb
103
107
  - lib/ruby2js/filter/return.rb