ruby2js 4.0.1 → 4.0.2

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: b77ba98b59e2dd3f500c4fa6c4974d6a082757becd31eb47efa841b51513ec28
4
- data.tar.gz: 3a868aa5a10b6562ad156c47bec44aed4060338f6aa747e90298dd890ae3095f
3
+ metadata.gz: eada6454a1374751fa61b2522291a4f7c61023ec0218ba98d7fdcb19e0067f0e
4
+ data.tar.gz: 4bef375ce47cef8733f0e08250dfbf4f6968e9a043aa53825d9198db3fafdd7f
5
5
  SHA512:
6
- metadata.gz: 2837170756fe4b6ca1f369d1dfe10c2ee6613f0572d54104354fb10df0b2f57dbe38c1dc4a44fa53f093af26bc6b826897144fbd5c5f0f6029885898878ff581
7
- data.tar.gz: 97b02c3f49d12c7eb6f84e5a504e6b5210f04bf4450f8923ee38927714aa749968839b67ac2ad04f508f7a4cc34010eab06ad4b3cc408415390107bc1a04d623
6
+ metadata.gz: 511f8917dfac3baaa45f33147430d23ea0a41e3ed2b74147d9589e1385a6f07d36aab029f47ba05f07f974c3543a7823a7c943b190e30fee2a240ce604d25d87
7
+ data.tar.gz: 61c8b8b5f3fbbecde1fb1bc0d23a35c13202a21467009665faba3b596607272fc1b1601f4f0156cf9d60ed80ff1e96ffa5204a1fa83b57430b729c6bc9b9b9d1
data/lib/ruby2js.rb CHANGED
@@ -92,6 +92,17 @@ module Ruby2JS
92
92
  include_only(options[:include_only]) if options[:include_only]
93
93
  include(options[:include]) if options[:include]
94
94
  exclude(options[:exclude]) if options[:exclude]
95
+
96
+ filters = options[:filters] || DEFAULTS
97
+ @modules_enabled =
98
+ (defined? Ruby2JS::Filter::ESM and
99
+ filters.include? Ruby2JS::Filter::ESM) or
100
+ (defined? Ruby2JS::Filter::CJS and
101
+ filters.include? Ruby2JS::Filter::CJS)
102
+ end
103
+
104
+ def modules_enabled?
105
+ @modules_enabled
95
106
  end
96
107
 
97
108
  def es2015
@@ -279,7 +290,7 @@ module Ruby2JS
279
290
 
280
291
  def self.parse(source, file=nil, line=1)
281
292
  buffer = Parser::Source::Buffer.new(file, line)
282
- buffer.source = source.encode('utf-8')
293
+ buffer.source = source.encode('UTF-8')
283
294
  parser = Parser::CurrentRuby.new
284
295
  parser.diagnostics.all_errors_are_fatal = true
285
296
  parser.diagnostics.consumer = lambda {|diagnostic| nil}
@@ -66,6 +66,7 @@ module Ruby2JS
66
66
  @comparison = :equality
67
67
  @or = :logical
68
68
  @underscored_private = true
69
+ @redoable = false
69
70
  end
70
71
 
71
72
  def width=(width)
@@ -243,6 +244,34 @@ module Ruby2JS
243
244
  end
244
245
  end
245
246
 
247
+ def redoable(block)
248
+ save_redoable = @redoable
249
+
250
+ has_redo = proc do |node|
251
+ node.children.any? do |child|
252
+ next false unless child.is_a? Parser::AST::Node
253
+ next true if child.type == :redo
254
+ next false if %i[for while while_post until until_post].include? child.type
255
+ has_redo[child]
256
+ end
257
+ end
258
+
259
+ @redoable = has_redo[@ast]
260
+
261
+ if @redoable
262
+ put es2015 ? 'let ' : 'var '
263
+ put "redo$#@sep"
264
+ puts 'do {'
265
+ put "redo$ = false#@sep"
266
+ scope block
267
+ put "#@nl} while(redo$)"
268
+ else
269
+ scope block
270
+ end
271
+ ensure
272
+ @redoable = save_redoable
273
+ end
274
+
246
275
  def timestamp(file)
247
276
  super
248
277
 
@@ -335,6 +364,7 @@ require 'ruby2js/converter/nil'
335
364
  require 'ruby2js/converter/nthref'
336
365
  require 'ruby2js/converter/opasgn'
337
366
  require 'ruby2js/converter/prototype'
367
+ require 'ruby2js/converter/redo'
338
368
  require 'ruby2js/converter/regexp'
339
369
  require 'ruby2js/converter/return'
340
370
  require 'ruby2js/converter/self'
@@ -32,7 +32,7 @@ module Ruby2JS
32
32
  elsif kw.type == :kwoptarg
33
33
  put kw.children.first
34
34
  unless kw.children.last == s(:send, nil, :undefined)
35
- put ' = '; parse kw.children.last
35
+ put '='; parse kw.children.last
36
36
  end
37
37
  elsif kw.type == :kwrestarg
38
38
  raise 'Rest arg requires ES2018' unless es2018
@@ -28,7 +28,7 @@ module Ruby2JS
28
28
  else
29
29
  put (@ast.type==:for_of ? ' of ' : ' in '); parse expression;
30
30
  end
31
- puts ') {'; scope block; sput '}'
31
+ puts ') {'; redoable block; sput '}'
32
32
  ensure
33
33
  @next_token = next_token
34
34
  @vars = vars if es2015
@@ -5,8 +5,16 @@ module Ruby2JS
5
5
  # (int 1))
6
6
 
7
7
  handle :next do |n=nil|
8
- raise Error.new("next argument #{ n.inspect }", @ast) if n
9
- put @next_token.to_s
8
+ if @next_token == :return
9
+ put 'return'
10
+ if n
11
+ put ' '
12
+ parse n
13
+ end
14
+ else
15
+ raise Error.new("next argument #{ n.inspect }", @ast) if n
16
+ put @next_token.to_s
17
+ end
10
18
  end
11
19
  end
12
20
  end
@@ -0,0 +1,14 @@
1
+ module Ruby2JS
2
+ class Converter
3
+
4
+ # (redo)
5
+
6
+ handle :redo do
7
+ unless @redoable and @next_token == :continue
8
+ raise Error.new("redo outside of loop", @ast)
9
+ end
10
+
11
+ put "redo$ = true#{@sep}continue"
12
+ end
13
+ end
14
+ end
@@ -22,7 +22,7 @@ module Ruby2JS
22
22
  end
23
23
  end
24
24
 
25
- put 'while ('; parse condition; puts ') {'; scope block; sput '}'
25
+ put 'while ('; parse condition; puts ') {'; redoable block; sput '}'
26
26
  ensure
27
27
  @next_token = next_token
28
28
  end
@@ -11,7 +11,7 @@ module Ruby2JS
11
11
  begin
12
12
  next_token, @next_token = @next_token, :continue
13
13
 
14
- puts 'do {'; scope block; sput '} while ('; parse condition; put ')'
14
+ puts 'do {'; redoable block; sput '} while ('; parse condition; put ')'
15
15
  ensure
16
16
  @next_token = next_token
17
17
  end
@@ -210,10 +210,10 @@ module Ruby2JS
210
210
  s(:block, s(:send, nil, :proc), s(:args, s(:arg, :s)),
211
211
  s(:send, s(:lvar, :s), :slice, s(:int, 1))))
212
212
  else
213
- # str.match(/.../g).map(s => s.match(/.../).slice(1))
213
+ # (str.match(/.../g) || []).map(s => s.match(/.../).slice(1))
214
214
  s(:block, s(:send,
215
- s(:send, process(target), :match, gpattern), :map),
216
- s(:args, s(:arg, :s)),
215
+ s(:or, s(:send, process(target), :match, gpattern), s(:array)),
216
+ :map), s(:args, s(:arg, :s)),
217
217
  s(:return, s(:send, s(:send, s(:lvar, :s), :match, arg),
218
218
  :slice, s(:int, 1))))
219
219
  end
@@ -508,6 +508,36 @@ module Ruby2JS
508
508
  elsif method == :floor and args.length == 0
509
509
  process S(:send, s(:const, nil, :Math), :floor, target)
510
510
 
511
+ elsif method == :rand and target == nil
512
+ if args.length == 0
513
+ process S(:send!, s(:const, nil, :Math), :random)
514
+ elsif %i[irange erange].include? args.first.type
515
+ range = args.first
516
+ multiplier = s(:send, range.children.last, :-, range.children.first)
517
+ if range.children.all? {|child| child.type == :int}
518
+ multiplier = s(:int, range.children.last.children.last - range.children.first.children.last)
519
+ multiplier = s(:int, multiplier.children.first + 1) if range.type == :irange
520
+ elsif range.type == :irange
521
+ if multiplier.children.last.type == :int
522
+ diff = multiplier.children.last.children.last - 1
523
+ multiplier = s(:send, *multiplier.children[0..1], s(:int, diff))
524
+ multiplier = multiplier.children.first if diff == 0
525
+ multiplier = s(:send, multiplier.children[0], :+, s(:int, -diff)) if diff < 0
526
+ else
527
+ multiplier = s(:send, multiplier, :+, s(:int, 1))
528
+ end
529
+ end
530
+ raw = s(:send, s(:send, s(:const, nil, :Math), :random), :*, multiplier)
531
+ if range.children.first != s(:int, 0)
532
+ raw = s(:send, raw, :+, range.children.first)
533
+ end
534
+ process S(:send, nil, :parseInt, raw)
535
+ else
536
+ process S(:send, nil, :parseInt,
537
+ s(:send, s(:send, s(:const, nil, :Math), :random),
538
+ :*, args.first))
539
+ end
540
+
511
541
  elsif method == :sum and args.length == 0
512
542
  process S(:send, target, :reduce, s(:block, s(:send, nil, :proc),
513
543
  s(:args, s(:arg, :a), s(:arg, :b)),
@@ -85,7 +85,6 @@ module Ruby2JS
85
85
  @react_props = []
86
86
  @react_methods = []
87
87
  @react_filter_functions = false
88
- @react_imports = false
89
88
  @jsx = false
90
89
  super
91
90
  end
@@ -102,15 +101,6 @@ module Ruby2JS
102
101
  @react_filter_functions = true
103
102
  end
104
103
 
105
- if \
106
- (defined? Ruby2JS::Filter::ESM and
107
- filters.include? Ruby2JS::Filter::ESM) or
108
- (defined? Ruby2JS::Filter::CJS and
109
- filters.include? Ruby2JS::Filter::CJS)
110
- then
111
- @react_imports = true
112
- end
113
-
114
104
  if \
115
105
  defined? Ruby2JS::Filter::JSX and
116
106
  filters.include? Ruby2JS::Filter::JSX
@@ -133,7 +123,7 @@ module Ruby2JS
133
123
  inheritance == s(:const, s(:const, nil, :React), :Component) or
134
124
  inheritance == s(:send, s(:const, nil, :React), :Component)
135
125
 
136
- prepend_list << REACT_IMPORTS[:React] if @react_imports
126
+ prepend_list << REACT_IMPORTS[:React] if modules_enabled?
137
127
 
138
128
  # traverse down to actual list of class statements
139
129
  if body.length == 1
@@ -445,7 +435,7 @@ module Ruby2JS
445
435
  node.children.first == s(:const, nil, :React) or
446
436
  node.children.first == s(:const, nil, :ReactDOM)
447
437
  then
448
- if @react_imports
438
+ if modules_enabled?
449
439
  prepend_list << REACT_IMPORTS[node.children.first.children.last]
450
440
  end
451
441
 
@@ -51,8 +51,10 @@ module Ruby2JS
51
51
  @stim_classes = Set.new
52
52
  stim_walk(node)
53
53
 
54
- prepend_list << (@options[:import_from_skypack] ?
55
- STIMULUS_IMPORT_SKYPACK : STIMULUS_IMPORT)
54
+ if modules_enabled?
55
+ prepend_list << (@options[:import_from_skypack] ?
56
+ STIMULUS_IMPORT_SKYPACK : STIMULUS_IMPORT)
57
+ end
56
58
 
57
59
  nodes = body
58
60
  if nodes.length == 1 and nodes.first&.type == :begin
@@ -303,11 +303,11 @@ module Ruby2JS
303
303
  def vlq(*mark)
304
304
  if @mark[0] == mark[0]
305
305
  return if @mark[-3..-1] == mark[-3..-1]
306
- @mappings << ',' unless @mappings == ''
306
+ @mappings += ',' unless @mappings == ''
307
307
  end
308
308
 
309
309
  while @mark[0] < mark[0]
310
- @mappings << ';'
310
+ @mappings += ';'
311
311
  @mark[0] += 1
312
312
  @mark[1] = 0
313
313
  end
@@ -322,16 +322,21 @@ module Ruby2JS
322
322
  data = diff << 1
323
323
  end
324
324
 
325
- encoded = ''
326
-
327
- begin
328
- digit = data & 0b11111
329
- data >>= 5
330
- digit |= 0b100000 if data > 0
331
- encoded << BASE64[digit]
332
- end while data > 0
325
+ if data <= 0b11111
326
+ # workaround https://github.com/opal/opal/issues/575
327
+ encoded = BASE64[data]
328
+ else
329
+ encoded = ''
330
+
331
+ begin
332
+ digit = data & 0b11111
333
+ data >>= 5
334
+ digit |= 0b100000 if data > 0
335
+ encoded += BASE64[digit]
336
+ end while data > 0
337
+ end
333
338
 
334
- @mappings << encoded
339
+ @mappings += encoded
335
340
  end
336
341
  end
337
342
 
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+ require 'sprockets/source_map_utils'
3
+ require 'ruby2js'
4
+ require 'ruby2js/version'
5
+
6
+ module Ruby2JS
7
+ module SprocketsTransformer
8
+ include Sprockets
9
+ VERSION = '1'
10
+
11
+ @@options = {}
12
+
13
+ def self.options=(options)
14
+ @@options = options
15
+ end
16
+
17
+ def self.cache_key
18
+ @cache_key ||= "#{name}:#{Ruby2JS::VERSION::STRING}:#{VERSION}".freeze
19
+ end
20
+
21
+ def self.call(input)
22
+ data = input[:data]
23
+
24
+ js, map = input[:cache].fetch([self.cache_key, data]) do
25
+ result = Ruby2JS.convert(data, {**@@options, file: input[:filename]})
26
+ [result.to_s, result.sourcemap.transform_keys {|key| key.to_s}]
27
+ end
28
+
29
+ map = SourceMapUtils.format_source_map(map, input)
30
+ map = SourceMapUtils.combine_source_maps(input[:metadata][:map], map)
31
+
32
+ { data: js, map: map }
33
+ end
34
+ end
35
+ end
36
+
37
+ Sprockets.register_mime_type 'application/ruby', extensions: ['.rb', '.js.rb']
38
+
39
+ Sprockets.register_transformer 'application/ruby', 'application/javascript',
40
+ Ruby2JS::SprocketsTransformer
@@ -2,7 +2,7 @@ module Ruby2JS
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 4
4
4
  MINOR = 0
5
- TINY = 1
5
+ TINY = 2
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
  end
data/ruby2js.gemspec CHANGED
@@ -19,5 +19,5 @@ Gem::Specification.new do |s|
19
19
  s.summary = "Minimal yet extensible Ruby to JavaScript conversion.".freeze
20
20
 
21
21
  s.add_dependency('parser')
22
- s.add_dependency('regexp_parser', '~> 2.0.3')
22
+ s.add_dependency('regexp_parser', '~> 2.1.1')
23
23
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby2js
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.1
4
+ version: 4.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sam Ruby
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2021-02-23 00:00:00.000000000 Z
12
+ date: 2021-03-03 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: parser
@@ -31,14 +31,14 @@ dependencies:
31
31
  requirements:
32
32
  - - "~>"
33
33
  - !ruby/object:Gem::Version
34
- version: 2.0.3
34
+ version: 2.1.1
35
35
  type: :runtime
36
36
  prerelease: false
37
37
  version_requirements: !ruby/object:Gem::Requirement
38
38
  requirements:
39
39
  - - "~>"
40
40
  - !ruby/object:Gem::Version
41
- version: 2.0.3
41
+ version: 2.1.1
42
42
  description: |2
43
43
  The base package maps Ruby syntax to JavaScript semantics.
44
44
  Filters may be provided to add Ruby-specific or framework specific
@@ -91,6 +91,7 @@ files:
91
91
  - lib/ruby2js/converter/nthref.rb
92
92
  - lib/ruby2js/converter/opasgn.rb
93
93
  - lib/ruby2js/converter/prototype.rb
94
+ - lib/ruby2js/converter/redo.rb
94
95
  - lib/ruby2js/converter/regexp.rb
95
96
  - lib/ruby2js/converter/return.rb
96
97
  - lib/ruby2js/converter/self.rb
@@ -149,9 +150,9 @@ files:
149
150
  - lib/ruby2js/haml.rb
150
151
  - lib/ruby2js/jsx.rb
151
152
  - lib/ruby2js/namespace.rb
152
- - lib/ruby2js/rails.rb
153
153
  - lib/ruby2js/serializer.rb
154
154
  - lib/ruby2js/sinatra.rb
155
+ - lib/ruby2js/sprockets.rb
155
156
  - lib/ruby2js/strict.rb
156
157
  - lib/ruby2js/version.rb
157
158
  - ruby2js.gemspec
data/lib/ruby2js/rails.rb DELETED
@@ -1,63 +0,0 @@
1
- # Example usage:
2
- #
3
- # $ echo "gem 'ruby2js', require: 'ruby2js/rails'" >> Gemfile
4
- # $ bundle update
5
- # $ rails generate controller Say hello
6
- # $ echo 'alert "Hello world!"' > app/views/say/hello.js.rb
7
- # $ rails server
8
- # $ curl http://localhost:3000/say/hello.js
9
- #
10
- # Using an optional filter:
11
- #
12
- # $ echo 'require "ruby2js/filter/functions"' > config/initializers/ruby2js.rb
13
- #
14
- # Asset Pipeline:
15
- #
16
- # Ruby2JS registers ".rb.js" extension.
17
- # You can add "ruby_thing.js.rb" to your app/javascript folder
18
- # and '= require ruby_thing' from other js sources.
19
- #
20
- # (options are not yet supported, but by requiring the appropriate files
21
- # as shown above, you can configure proejct wide.)
22
- require 'ruby2js'
23
-
24
- module Ruby2JS
25
- module Rails
26
- class Template
27
- cattr_accessor :default_format
28
- self.default_format = Mime[:js]
29
- def self.call(template, source)
30
- "Ruby2JS.convert(#{template.source.inspect}, file: source).to_s"
31
- end
32
- end
33
-
34
- ActiveSupport.on_load(:action_view) do
35
- ActionView::Template.register_template_handler :rb, Template
36
- end
37
-
38
- class SprocketProcessor
39
- def initialize(file = nil)
40
- @file = file
41
- end
42
- def render(context , _)
43
- context = context.instance_eval { binding } unless context.is_a? Binding
44
- Ruby2JS.convert(File.read(@file), binding: context).to_s
45
- end
46
- end
47
-
48
- class Engine < ::Rails::Engine
49
- engine_name "ruby2js"
50
-
51
- config.app_generators.javascripts true
52
- config.app_generators.javascript_engine :rb
53
-
54
- config.assets.configure do |env|
55
- env.register_mime_type 'text/ruby', extensions: ['.js.rb', '.rb']
56
- env.register_transformer 'text/ruby', 'text/javascript', SprocketProcessor
57
- env.register_preprocessor 'text/javascript', SprocketProcessor
58
- end
59
- end
60
-
61
- end
62
-
63
- end