ruby2js 3.4.0 → 3.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +128 -20
- data/lib/ruby2js.rb +30 -2
- data/lib/ruby2js/converter.rb +7 -5
- data/lib/ruby2js/converter/block.rb +5 -0
- data/lib/ruby2js/converter/class2.rb +63 -20
- data/lib/ruby2js/converter/def.rb +1 -1
- data/lib/ruby2js/converter/import.rb +17 -1
- data/lib/ruby2js/converter/ivar.rb +10 -2
- data/lib/ruby2js/converter/literal.rb +14 -2
- data/lib/ruby2js/converter/send.rb +4 -3
- data/lib/ruby2js/converter/xstr.rb +1 -1
- data/lib/ruby2js/filter/active_functions.rb +43 -0
- data/lib/ruby2js/filter/camelCase.rb +4 -3
- data/lib/ruby2js/filter/esm.rb +96 -4
- data/lib/ruby2js/filter/functions.rb +14 -0
- data/lib/ruby2js/filter/node.rb +95 -74
- data/lib/ruby2js/filter/nokogiri.rb +3 -29
- data/lib/ruby2js/filter/return.rb +2 -0
- data/lib/ruby2js/filter/securerandom.rb +33 -0
- data/lib/ruby2js/filter/vue.rb +9 -0
- data/lib/ruby2js/rails.rb +15 -9
- data/lib/ruby2js/serializer.rb +4 -2
- data/lib/ruby2js/version.rb +1 -1
- data/ruby2js.gemspec +1 -1
- metadata +9 -7
- data/lib/ruby2js/filter/esm_migration.rb +0 -72
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7fa9e6949c8d7d1f3f5cb549dc234a2b559d032bc9b5b236d123f68b62ecd763
|
4
|
+
data.tar.gz: e89542553f4db3caa7ceda112542a3a7fceb468d23d8a15cb9b416954c054d1f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a46d662b6be3a5e7a7242c1249705dcc5b705bfa984443ebedbb766c241aff365ce6f45fbea6b774f6646ce807c6d7f595becb841866f1a878ae65f69b409430
|
7
|
+
data.tar.gz: 27091e81578f5cebad30132ef54c3e08a1a32516233a0cab084c15dca5b361c7a2c7602dd3ba886d57db23301bb5a7d54d106cabba7a5a71d5989fc0b959533d
|
data/README.md
CHANGED
@@ -40,9 +40,6 @@ For example:
|
|
40
40
|
* Any block becomes and explicit argument `new Promise do; y(); end` becomes `new Promise(function() {y()})`
|
41
41
|
* regular expressions are mapped to js
|
42
42
|
* `raise` becomes `throw`
|
43
|
-
* expressions enclosed in backtick operators (\`\`) and `%x{}` literals are
|
44
|
-
evaluated in the context of the caller and the results are inserted
|
45
|
-
into the generated JavaScript.
|
46
43
|
|
47
44
|
Ruby attribute accessors, methods defined with no parameters and no
|
48
45
|
parenthesis, as well as setter method definitions, are
|
@@ -81,6 +78,18 @@ require 'ruby2js/filter/functions'
|
|
81
78
|
puts Ruby2JS.convert('"2A".to_i(16)')
|
82
79
|
```
|
83
80
|
|
81
|
+
Host variable substitution:
|
82
|
+
|
83
|
+
```ruby
|
84
|
+
puts Ruby2JS.convert("@name", ivars: {:@name => "Joe"})
|
85
|
+
```
|
86
|
+
|
87
|
+
Host expression evalution -- potentially unsafe, use only if you trust
|
88
|
+
the source being converted::
|
89
|
+
```ruby
|
90
|
+
i = 7; puts Ruby2JS.convert("i = `i`", binding: binding)
|
91
|
+
```
|
92
|
+
|
84
93
|
Enable ES2015 support:
|
85
94
|
|
86
95
|
```ruby
|
@@ -129,7 +138,7 @@ Introduction
|
|
129
138
|
|
130
139
|
JavaScript is a language where `0` is considered `false`, strings are
|
131
140
|
immutable, and the behaviors for operators like `==` are, at best,
|
132
|
-
[convoluted](
|
141
|
+
[convoluted](https://zero.milosz.ca/).
|
133
142
|
|
134
143
|
Any attempt to bridge the semantics of Ruby and JavaScript will involve
|
135
144
|
trade-offs. Consider the following expression:
|
@@ -144,10 +153,10 @@ quite different if `a` is a Hash.
|
|
144
153
|
|
145
154
|
One way to resolve this is to change the way indexing operators are evaluated,
|
146
155
|
and to provide a runtime library that adds properties to global JavaScript
|
147
|
-
objects to handle this. This is the approach that [Opal](
|
156
|
+
objects to handle this. This is the approach that [Opal](https://opalrb.com/)
|
148
157
|
takes. It is a fine approach, with a number of benefits. It also has some
|
149
158
|
notable drawbacks. For example,
|
150
|
-
[readability](
|
159
|
+
[readability](https://opalrb.com/try/#code:a%20%3D%20%22abc%22%3B%20puts%20a[-1])
|
151
160
|
and
|
152
161
|
[compatibility with other frameworks](https://github.com/opal/opal/issues/400).
|
153
162
|
|
@@ -169,7 +178,7 @@ negative at runtime.
|
|
169
178
|
This quickly gets into gray areas. `each` in Ruby is a common method that
|
170
179
|
facilitates iteration over arrays. `forEach` is the JavaScript equivalent.
|
171
180
|
Mapping this is fine until you start using a framework like jQuery which
|
172
|
-
provides a function named [each](
|
181
|
+
provides a function named [each](https://api.jquery.com/jQuery.each/).
|
173
182
|
|
174
183
|
Fortunately, Ruby provides `?` and `!` as legal suffixes for method names,
|
175
184
|
Ruby2js filters do an exact match, so if you select a filter that maps `each`
|
@@ -192,9 +201,7 @@ Ruby2JS::Filter.exclude :each
|
|
192
201
|
```
|
193
202
|
|
194
203
|
Static transformations and runtime libraries aren't aren’t mutually exclusive.
|
195
|
-
With enough of each, one could reproduce any functionality desired.
|
196
|
-
forewarned, that implementing a function like `method_missing` would require a
|
197
|
-
_lot_ of work.
|
204
|
+
With enough of each, one could reproduce any functionality desired.
|
198
205
|
|
199
206
|
Integrations
|
200
207
|
---
|
@@ -237,8 +244,10 @@ the script.
|
|
237
244
|
|
238
245
|
* <a id="functions" href="https://github.com/rubys/ruby2js/blob/master/lib/ruby2js/filter/functions.rb">functions</a>
|
239
246
|
|
247
|
+
* `.abs` becomes `Math.abs()`
|
240
248
|
* `.all?` becomes `.every`
|
241
249
|
* `.any?` becomes `.some`
|
250
|
+
* `.ceil` becomes `Math.ceil()`
|
242
251
|
* `.chr` becomes `fromCharCode`
|
243
252
|
* `.clear` becomes `.length = 0`
|
244
253
|
* `.delete` becomes `delete target[arg]`
|
@@ -253,6 +262,7 @@ the script.
|
|
253
262
|
* `.find_index` becomes `findIndex`
|
254
263
|
* `.first` becomes `[0]`
|
255
264
|
* `.first(n)` becomes `.slice(0, n)`
|
265
|
+
* `.floor` becomes `Math.floor()`
|
256
266
|
* `.gsub` becomes `replace(//g)`
|
257
267
|
* `.include?` becomes `.indexOf() != -1`
|
258
268
|
* `.inspect` becomes `JSON.stringify()`
|
@@ -271,6 +281,7 @@ the script.
|
|
271
281
|
* `.respond_to?` becomes `right in left`
|
272
282
|
* `.rstrip` becomes `.replace(/s+$/, "")`
|
273
283
|
* `.scan` becomes `.match(//g)`
|
284
|
+
* `.sum` becomes `.reduce(function(a, b) {a + b}, 0)`
|
274
285
|
* `.start_with?` becomes `.substring(0, arg.length) == arg`
|
275
286
|
* `.upto(lim)` becomes `for (var i=num; i<=lim; i+=1)`
|
276
287
|
* `.downto(lim)` becomes `for (var i=num; i>=lim; i-=1)`
|
@@ -317,6 +328,20 @@ the script.
|
|
317
328
|
|
318
329
|
* `.class` becomes `.constructor`
|
319
330
|
|
331
|
+
* <a id="active_functions" href="https://github.com/rubys/ruby2js/blob/master/lib/ruby2js/filter/active_functions.rb">active_functions</a>
|
332
|
+
|
333
|
+
Provides functionality inspired by Rails' ActiveSupport. Works in conjunction
|
334
|
+
with the tiny NPM dependency `@ruby2js/active-functions` which must be added to
|
335
|
+
your application.
|
336
|
+
|
337
|
+
* `value.blank?` becomes `blank$(value)`
|
338
|
+
* `value.present?` becomes `present$(value)`
|
339
|
+
* `value.presence` becomes `presence$(value)`
|
340
|
+
|
341
|
+
Note: these conversions are only done if eslevel >= 2015. Import statements
|
342
|
+
will be added to the top of the code output automatically. By default they
|
343
|
+
will be `@ruby2js/active-functions`, but you can pass an `import_from_skypack: true` option to `convert` to use the Skypack CDN instead.
|
344
|
+
|
320
345
|
* <a id="tagged_templates" href="https://github.com/rubys/ruby2js/blob/master/lib/ruby2js/filter/tagged_templates.rb">tagged_templates</a>
|
321
346
|
|
322
347
|
Allows you to turn certain method calls with a string argument into tagged
|
@@ -382,6 +407,59 @@ the script.
|
|
382
407
|
# => export { one, two, three as default }
|
383
408
|
```
|
384
409
|
|
410
|
+
If the "autoexports" option is `true`, all top level modules, classes,
|
411
|
+
methods and constants will automatically be exported.
|
412
|
+
|
413
|
+
The esm filter also provides a way to specify "autoimports" when you run the
|
414
|
+
conversion. It will add the relevant import statements automatically whenever
|
415
|
+
a particular class or function name is referenced. These can be either default
|
416
|
+
or named exports. Simply provide an `autoimports` hash with one or more keys
|
417
|
+
to the `Ruby2JS.convert` method. Examples:
|
418
|
+
|
419
|
+
```ruby
|
420
|
+
require "ruby2js/filter/esm"
|
421
|
+
puts Ruby2JS.convert('class MyElement < LitElement; end',
|
422
|
+
eslevel: 2020, autoimports: {[:LitElement] => "lit-element"})
|
423
|
+
```
|
424
|
+
|
425
|
+
```js
|
426
|
+
// JavaScript output:
|
427
|
+
import { LitElement } from "lit-element"
|
428
|
+
class MyElement extends LitElement {}
|
429
|
+
```
|
430
|
+
|
431
|
+
```ruby
|
432
|
+
require "ruby2js/filter/esm"
|
433
|
+
puts Ruby2JS.convert('AWN.new({position: "top-right"}).success("Hello World")',
|
434
|
+
eslevel: 2020, autoimports: {:AWN => "awesome-notifications"})
|
435
|
+
```
|
436
|
+
|
437
|
+
```js
|
438
|
+
// JavaScript output:
|
439
|
+
import AWN from "awesome-notifications"
|
440
|
+
new AWN({position: "top-right"}).success("Hello World")
|
441
|
+
```
|
442
|
+
|
443
|
+
The esm filter is able to recognize if you are defining a class or function
|
444
|
+
within the code itself and it won't add that import statement accordingly.
|
445
|
+
If for some reason you wish to disable autoimports entirely on a file-by-file
|
446
|
+
basis (for instance when using the Webpack loader), you can add a magic comment
|
447
|
+
to the top of the code:
|
448
|
+
|
449
|
+
```ruby
|
450
|
+
require "ruby2js/filter/esm"
|
451
|
+
puts Ruby2JS.convert(
|
452
|
+
"# autoimports: false\n" +
|
453
|
+
'AWN.new({position: "top-right"}).success("Hello World")',
|
454
|
+
eslevel: 2020, autoimports: {:AWN => "awesome-notifications"}
|
455
|
+
)
|
456
|
+
```
|
457
|
+
|
458
|
+
```js
|
459
|
+
// autoimports: false
|
460
|
+
new AWN({position: "top-right"}).success("Hello World")
|
461
|
+
```
|
462
|
+
|
385
463
|
* <a id="node" href="https://github.com/rubys/ruby2js/blob/master/spec/node_spec.rb">node</a>
|
386
464
|
|
387
465
|
* `` `command` `` becomes `child_process.execSync("command", {encoding: "utf8"})`
|
@@ -389,24 +467,34 @@ the script.
|
|
389
467
|
* `__dir__` becomes `__dirname`
|
390
468
|
* `Dir.chdir` becomes `process.chdir`
|
391
469
|
* `Dir.entries` becomes `fs.readdirSync`
|
470
|
+
* `Dir.home` becomes `os.homedir()`
|
392
471
|
* `Dir.mkdir` becomes `fs.mkdirSync`
|
393
472
|
* `Dir.mktmpdir` becomes `fs.mkdtempSync`
|
394
473
|
* `Dir.pwd` becomes `process.cwd`
|
395
474
|
* `Dir.rmdir` becomes `fs.rmdirSync`
|
475
|
+
* `Dir.tmpdir` becomes `os.tmpdir()`
|
396
476
|
* `ENV` becomes `process.env`
|
397
477
|
* `__FILE__` becomes `__filename`
|
478
|
+
* `File.absolute_path` becomes `path.resolve`
|
479
|
+
* `File.absolute_path?` becomes `path.isAbsolute`
|
480
|
+
* `File.basename` becomes `path.basename`
|
398
481
|
* `File.chmod` becomes `fs.chmodSync`
|
399
482
|
* `File.chown` becomes `fs.chownSync`
|
400
483
|
* `File.cp` becomes `fs.copyFileSync`
|
484
|
+
* `File.dirname` becomes `path.dirname`
|
401
485
|
* `File.exist?` becomes `fs.existsSync`
|
486
|
+
* `File.extname` becomes `path.extname`
|
487
|
+
* `File.join` becomes `path.join`
|
402
488
|
* `File.lchmod` becomes `fs.lchmodSync`
|
403
489
|
* `File.link` becomes `fs.linkSync`
|
404
490
|
* `File.ln` becomes `fs.linkSync`
|
405
491
|
* `File.lstat` becomes `fs.lstatSync`
|
492
|
+
* `File::PATH_SEPARATOR` becomes `path.delimiter`
|
406
493
|
* `File.read` becomes `fs.readFileSync`
|
407
494
|
* `File.readlink` becomes `fs.readlinkSync`
|
408
495
|
* `File.realpath` becomes `fs.realpathSync`
|
409
496
|
* `File.rename` becomes `fs.renameSync`
|
497
|
+
* `File::SEPARATOR` becomes `path.sep`
|
410
498
|
* `File.stat` becomes `fs.statSync`
|
411
499
|
* `File.symlink` becomes `fs.symlinkSync`
|
412
500
|
* `File.truncate` becomes `fs.truncateSync`
|
@@ -600,8 +688,16 @@ Additionally, the `functions` filter will provide the following conversion:
|
|
600
688
|
* `Array(x)` becomes `Array.from(x)`
|
601
689
|
* `.inject(n) {}` becomes `.reduce(() => {}, n)`
|
602
690
|
|
603
|
-
|
604
|
-
parameter
|
691
|
+
Keyword arguments and optional keyword arguments will be mapped to
|
692
|
+
parameter destructuring.
|
693
|
+
|
694
|
+
Classes defined with a `method_missing` method will emit a `Proxy` object
|
695
|
+
for each instance that will forward calls. Note that in order to forward
|
696
|
+
arguments, this proxy will return a function that will need to be called,
|
697
|
+
making it impossible to proxy attributes/getters. As a special accommodation,
|
698
|
+
if the `method_missing` method is defined to only accept a single parameter
|
699
|
+
it will be called with only the method name, and it is free to return
|
700
|
+
either values or functions.
|
605
701
|
|
606
702
|
ES2016 support
|
607
703
|
---
|
@@ -610,6 +706,9 @@ When option `eslevel: 2016` is provided, the following additional
|
|
610
706
|
conversion is made:
|
611
707
|
|
612
708
|
* `a ** b` becomes `a ** b`
|
709
|
+
|
710
|
+
Additionally the following conversions is added to the `functions` filter:
|
711
|
+
|
613
712
|
* `.include?` becomes `.includes`
|
614
713
|
|
615
714
|
ES2017 support
|
@@ -620,7 +719,15 @@ conversions are made by the `functions` filter:
|
|
620
719
|
|
621
720
|
* `.values()` becomes `Object.values()`
|
622
721
|
* `.entries()` becomes `Object.entries()`
|
623
|
-
* `.each_pair {}` becomes `for (let [key, value] of Object.entries()) {}
|
722
|
+
* `.each_pair {}` becomes `for (let [key, value] of Object.entries()) {}`
|
723
|
+
|
724
|
+
async support:
|
725
|
+
|
726
|
+
* `async def` becomes `async function`
|
727
|
+
* `async lambda` becomes `async =>`
|
728
|
+
* `async proc` becomes `async =>`
|
729
|
+
* `async ->` becomes `async =>`
|
730
|
+
* `foo bar, async do...end` becomes `foo(bar, async () => {})`
|
624
731
|
|
625
732
|
ES2018 support
|
626
733
|
---
|
@@ -640,8 +747,8 @@ When option `eslevel: 2019` is provided, the following additional
|
|
640
747
|
conversion is made by the `functions` filter:
|
641
748
|
|
642
749
|
* `.flatten` becomes `.flat(Infinity)`
|
643
|
-
* `.lstrip` becomes `.trimEnd
|
644
|
-
* `.rstrip` becomes `.trimStart
|
750
|
+
* `.lstrip` becomes `.trimEnd`
|
751
|
+
* `.rstrip` becomes `.trimStart`
|
645
752
|
* `a.to_h` becomes `Object.fromEntries(a)`
|
646
753
|
* `Hash[a]` becomes `Object.fromEntries(a)`
|
647
754
|
|
@@ -667,27 +774,28 @@ conversions are made:
|
|
667
774
|
|
668
775
|
* `x ||= 1` becomes `x ||= 1`
|
669
776
|
* `x &&= 1` becomes `x &&= 1`
|
777
|
+
* `1000000.000001` becomes `1_000_000.000_001`
|
670
778
|
|
671
779
|
Picking a Ruby to JS mapping tool
|
672
780
|
---
|
673
781
|
|
674
782
|
> dsl — A domain specific language, where code is written in one language and
|
675
783
|
> errors are given in another.
|
676
|
-
> -- [Devil’s Dictionary of Programming](
|
784
|
+
> -- [Devil’s Dictionary of Programming](https://programmingisterrible.com/post/65781074112/devils-dictionary-of-programming)
|
677
785
|
|
678
786
|
If you simply want to get a job done, and would like a mature and tested
|
679
787
|
framework, and only use one of the many integrations that
|
680
|
-
[Opal](
|
788
|
+
[Opal](https://opalrb.com/) provides, then Opal is the way to go right now.
|
681
789
|
|
682
790
|
ruby2js is for those that want to produce JavaScript that looks like it
|
683
791
|
wasn’t machine generated, and want the absolute bare minimum in terms of
|
684
792
|
limitations as to what JavaScript can be produced.
|
685
793
|
|
686
|
-
[Try](
|
687
|
-
[Compare](
|
794
|
+
[Try](https://intertwingly.net/projects/ruby2js) for yourself.
|
795
|
+
[Compare](https://opalrb.com/try/#code:).
|
688
796
|
|
689
797
|
And, of course, the right solution might be to use
|
690
|
-
[CoffeeScript](
|
798
|
+
[CoffeeScript](https://coffeescript.org/) instead.
|
691
799
|
|
692
800
|
License
|
693
801
|
---
|
data/lib/ruby2js.rb
CHANGED
@@ -17,6 +17,7 @@ module Ruby2JS
|
|
17
17
|
|
18
18
|
@@eslevel_default = 2009 # ecmascript 5
|
19
19
|
@@strict_default = false
|
20
|
+
@@module_default = nil
|
20
21
|
|
21
22
|
def self.eslevel_default
|
22
23
|
@@eslevel_default
|
@@ -34,6 +35,14 @@ module Ruby2JS
|
|
34
35
|
@@strict_default = level
|
35
36
|
end
|
36
37
|
|
38
|
+
def self.module_default
|
39
|
+
@@module_default
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.module_default=(module_type)
|
43
|
+
@@module_default = module_type
|
44
|
+
end
|
45
|
+
|
37
46
|
module Filter
|
38
47
|
DEFAULTS = []
|
39
48
|
|
@@ -52,11 +61,19 @@ module Ruby2JS
|
|
52
61
|
include Ruby2JS::Filter
|
53
62
|
BINARY_OPERATORS = Converter::OPERATORS[2..-1].flatten
|
54
63
|
|
64
|
+
attr_accessor :prepend_list, :disable_autoimports
|
65
|
+
|
55
66
|
def initialize(comments)
|
56
67
|
@comments = comments
|
68
|
+
|
69
|
+
# check if magic comment is present:
|
70
|
+
first_comment = @comments.values.first&.map(&:text)&.first
|
71
|
+
@disable_autoimports = first_comment&.include?(" autoimports: false")
|
72
|
+
@disable_autoexports = first_comment&.include?(" autoexports: false")
|
73
|
+
|
57
74
|
@ast = nil
|
58
75
|
@exclude_methods = []
|
59
|
-
@
|
76
|
+
@prepend_list = Set.new
|
60
77
|
end
|
61
78
|
|
62
79
|
def options=(options)
|
@@ -129,6 +146,7 @@ module Ruby2JS
|
|
129
146
|
def on_method(node); on_send(node); end
|
130
147
|
def on_prop(node); on_array(node); end
|
131
148
|
def on_prototype(node); on_begin(node); end
|
149
|
+
def on_send!(node); on_send(node); end
|
132
150
|
def on_sendw(node); on_send(node); end
|
133
151
|
def on_undefined?(node); on_defined?(node); end
|
134
152
|
def on_nil(node); end
|
@@ -162,6 +180,7 @@ module Ruby2JS
|
|
162
180
|
def self.convert(source, options={})
|
163
181
|
options[:eslevel] ||= @@eslevel_default
|
164
182
|
options[:strict] = @@strict_default if options[:strict] == nil
|
183
|
+
options[:module] ||= @@module_default || :esm
|
165
184
|
|
166
185
|
if Proc === source
|
167
186
|
file,line = source.source_location
|
@@ -175,7 +194,7 @@ module Ruby2JS
|
|
175
194
|
source = ast.loc.expression.source_buffer.source
|
176
195
|
else
|
177
196
|
ast, comments = parse( source, options[:file] )
|
178
|
-
comments = Parser::Source::Comment.associate(ast, comments)
|
197
|
+
comments = ast ? Parser::Source::Comment.associate(ast, comments) : {}
|
179
198
|
end
|
180
199
|
|
181
200
|
filters = (options[:filters] || Filter::DEFAULTS)
|
@@ -193,6 +212,12 @@ module Ruby2JS
|
|
193
212
|
|
194
213
|
filter.options = options
|
195
214
|
ast = filter.process(ast)
|
215
|
+
|
216
|
+
unless filter.prepend_list.empty?
|
217
|
+
prepend = filter.prepend_list.sort_by {|ast| ast.type == :import ? 0 : 1}
|
218
|
+
prepend.reject! {|ast| ast.type == :import} if filter.disable_autoimports
|
219
|
+
ast = Parser::AST::Node.new(:begin, [*prepend, ast])
|
220
|
+
end
|
196
221
|
end
|
197
222
|
|
198
223
|
ruby2js = Ruby2JS::Converter.new(ast, comments)
|
@@ -203,6 +228,7 @@ module Ruby2JS
|
|
203
228
|
ruby2js.strict = options[:strict]
|
204
229
|
ruby2js.comparison = options[:comparison] || :equality
|
205
230
|
ruby2js.or = options[:or] || :logical
|
231
|
+
ruby2js.module_type = options[:module] || :esm
|
206
232
|
ruby2js.underscored_private = (options[:eslevel] < 2020) || options[:underscored_private]
|
207
233
|
if ruby2js.binding and not ruby2js.ivars
|
208
234
|
ruby2js.ivars = ruby2js.binding.eval \
|
@@ -221,6 +247,8 @@ module Ruby2JS
|
|
221
247
|
|
222
248
|
ruby2js.timestamp options[:file]
|
223
249
|
|
250
|
+
ruby2js.file_name = options[:file] || ast&.loc&.expression&.source_buffer&.name || ''
|
251
|
+
|
224
252
|
ruby2js
|
225
253
|
end
|
226
254
|
|
data/lib/ruby2js/converter.rb
CHANGED
@@ -3,9 +3,11 @@ require 'ruby2js/serializer'
|
|
3
3
|
module Ruby2JS
|
4
4
|
class Error < NotImplementedError
|
5
5
|
def initialize(message, ast)
|
6
|
-
|
7
|
-
|
8
|
-
|
6
|
+
if ast.loc
|
7
|
+
message += ' at ' + ast.loc.expression.source_buffer.name.to_s
|
8
|
+
message += ':' + ast.loc.expression.line.inspect
|
9
|
+
message += ':' + ast.loc.expression.column.to_s
|
10
|
+
end
|
9
11
|
super(message)
|
10
12
|
end
|
11
13
|
end
|
@@ -128,7 +130,7 @@ module Ruby2JS
|
|
128
130
|
Parser::AST::Node.new(type, args)
|
129
131
|
end
|
130
132
|
|
131
|
-
attr_accessor :strict, :eslevel, :comparison, :or, :underscored_private
|
133
|
+
attr_accessor :strict, :eslevel, :module_type, :comparison, :or, :underscored_private
|
132
134
|
|
133
135
|
def es2015
|
134
136
|
@eslevel >= 2015
|
@@ -246,7 +248,7 @@ module Ruby2JS
|
|
246
248
|
if ast.loc and ast.loc.expression
|
247
249
|
filename = ast.loc.expression.source_buffer.name
|
248
250
|
if filename and not filename.empty?
|
249
|
-
@timestamps[filename] ||= File.mtime(filename)
|
251
|
+
@timestamps[filename] ||= File.mtime(filename) rescue nil
|
250
252
|
end
|
251
253
|
end
|
252
254
|
|
@@ -9,6 +9,11 @@ module Ruby2JS
|
|
9
9
|
|
10
10
|
handle :block do |call, args, block|
|
11
11
|
|
12
|
+
if es2017 and call.children.last == s(:send, nil, :async)
|
13
|
+
return parse call.updated(nil, [*call.children[0..-2],
|
14
|
+
s(:send, nil, :async, s(:block, s(:send, nil, :proc), args, block))])
|
15
|
+
end
|
16
|
+
|
12
17
|
if \
|
13
18
|
@state == :statement and args.children.length == 1 and
|
14
19
|
call.children.first and call.children.first.type == :begin and
|