ruby2js 4.0.1 → 4.0.2

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 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