opal 1.4.1 → 1.5.0.rc1

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.
Files changed (89) hide show
  1. checksums.yaml +4 -4
  2. data/.eslintrc.js +5 -3
  3. data/.rubocop.yml +1 -0
  4. data/UNRELEASED.md +37 -2
  5. data/benchmark-ips/bm_js_symbols_vs_strings.rb +39 -14
  6. data/docs/releasing.md +10 -2
  7. data/lib/opal/ast/matcher.rb +77 -0
  8. data/lib/opal/cache.rb +1 -1
  9. data/lib/opal/cli_runners/applescript.rb +2 -0
  10. data/lib/opal/compiler.rb +18 -9
  11. data/lib/opal/nodes/call.rb +73 -28
  12. data/lib/opal/nodes/def.rb +31 -27
  13. data/lib/opal/nodes/definitions.rb +2 -0
  14. data/lib/opal/nodes/helpers.rb +4 -23
  15. data/lib/opal/nodes/if.rb +222 -0
  16. data/lib/opal/nodes/iter.rb +41 -37
  17. data/lib/opal/nodes/literal.rb +2 -2
  18. data/lib/opal/nodes/masgn.rb +15 -17
  19. data/lib/opal/nodes/node_with_args/shortcuts.rb +100 -0
  20. data/lib/opal/nodes/node_with_args.rb +1 -0
  21. data/lib/opal/nodes/top.rb +26 -10
  22. data/lib/opal/nodes.rb +0 -1
  23. data/lib/opal/parser/default_config.rb +3 -2
  24. data/lib/opal/repl.rb +1 -1
  25. data/lib/opal/rewriter.rb +13 -6
  26. data/lib/opal/rewriters/base.rb +12 -1
  27. data/lib/opal/rewriters/rubyspec/filters_rewriter.rb +1 -0
  28. data/lib/opal/version.rb +1 -1
  29. data/opal/corelib/array.rb +23 -28
  30. data/opal/corelib/binding.rb +14 -4
  31. data/opal/corelib/constants.rb +3 -3
  32. data/opal/corelib/hash.rb +2 -2
  33. data/opal/corelib/irb.rb +192 -0
  34. data/opal/corelib/math/polyfills.rb +127 -0
  35. data/opal/corelib/math.rb +14 -194
  36. data/opal/corelib/module.rb +23 -25
  37. data/opal/corelib/number.rb +63 -14
  38. data/opal/corelib/regexp.rb +2 -0
  39. data/opal/corelib/runtime.js +56 -20
  40. data/opal/corelib/string.rb +38 -59
  41. data/opal/corelib/time.rb +106 -68
  42. data/opal/opal/full.rb +0 -1
  43. data/opal/opal.rb +4 -1
  44. data/spec/filters/bugs/date.rb +0 -3
  45. data/spec/filters/bugs/datetime.rb +65 -0
  46. data/spec/filters/bugs/float.rb +0 -18
  47. data/spec/filters/bugs/hash.rb +0 -2
  48. data/spec/filters/bugs/language.rb +0 -3
  49. data/spec/filters/bugs/marshal.rb +0 -1
  50. data/spec/filters/bugs/string.rb +0 -30
  51. data/spec/filters/bugs/time.rb +18 -8
  52. data/spec/lib/cli_spec.rb +2 -2
  53. data/spec/lib/compiler_spec.rb +8 -8
  54. data/spec/lib/rewriters/base_spec.rb +1 -1
  55. data/spec/lib/rewriters/binary_operator_assignment_spec.rb +34 -59
  56. data/spec/lib/rewriters/block_to_iter_spec.rb +3 -6
  57. data/spec/lib/rewriters/dot_js_syntax_spec.rb +2 -5
  58. data/spec/lib/rewriters/for_rewriter_spec.rb +0 -1
  59. data/spec/lib/rewriters/forward_args_spec.rb +2 -3
  60. data/spec/lib/rewriters/js_reserved_words_spec.rb +2 -15
  61. data/spec/lib/rewriters/logical_operator_assignment_spec.rb +64 -89
  62. data/spec/lib/rewriters/numblocks_spec.rb +3 -5
  63. data/spec/lib/rewriters/opal_engine_check_spec.rb +2 -14
  64. data/spec/lib/rewriters/rubyspec/filters_rewriter_spec.rb +10 -2
  65. data/spec/opal/compiler/irb_spec.rb +4 -0
  66. data/spec/opal/core/language/super_spec.rb +26 -0
  67. data/spec/opal/core/regexp/assertions_spec.rb +19 -0
  68. data/spec/opal/core/string/to_proc_spec.rb +19 -0
  69. data/spec/ruby_specs +4 -0
  70. data/spec/support/rewriters_helper.rb +43 -23
  71. data/stdlib/date/date_time.rb +71 -0
  72. data/stdlib/date/formatters.rb +28 -0
  73. data/stdlib/date/infinity.rb +73 -0
  74. data/stdlib/date.rb +77 -214
  75. data/stdlib/opal/repl_js.rb +1 -1
  76. data/stdlib/{opal/replutils.rb → opal-replutils.rb} +3 -3
  77. data/stdlib/time.rb +39 -2
  78. data/stdlib/uri.rb +53 -0
  79. data/tasks/performance/asciidoctor_test.rb.erb +3 -1
  80. data/tasks/performance/optimization_status.rb +3 -2
  81. data/tasks/performance.rake +69 -35
  82. data/tasks/testing.rake +1 -0
  83. data/test/opal/test_uri.rb +35 -0
  84. data/yarn.lock +27 -5
  85. metadata +31 -18
  86. data/lib/opal/nodes/csend.rb +0 -24
  87. data/lib/opal/rewriters/explicit_writer_return.rb +0 -59
  88. data/spec/lib/rewriters/explicit_writer_return_spec.rb +0 -186
  89. data/stdlib/nodejs/irb.rb +0 -43
data/stdlib/date.rb CHANGED
@@ -1,77 +1,10 @@
1
+ require 'forwardable'
2
+ require 'date/infinity'
3
+ require 'time'
4
+
1
5
  class Date
2
6
  include Comparable
3
-
4
- class Infinity < Numeric
5
- include Comparable
6
-
7
- def initialize(d = 1)
8
- @d = d <=> 0
9
- end
10
-
11
- attr_reader :d
12
-
13
- def zero?
14
- false
15
- end
16
-
17
- def finite?
18
- false
19
- end
20
-
21
- def infinite?
22
- d.nonzero?
23
- end
24
-
25
- def nan?
26
- d.zero?
27
- end
28
-
29
- def abs
30
- self.class.new
31
- end
32
-
33
- def -@
34
- self.class.new(-d)
35
- end
36
-
37
- def +@
38
- self.class.new(+d)
39
- end
40
-
41
- def <=>(other)
42
- case other
43
- when Infinity
44
- d <=> other.d
45
- when Numeric
46
- d
47
- else
48
- begin
49
- l, r = other.coerce(self)
50
- l <=> r
51
- rescue NoMethodError
52
- nil
53
- end
54
- end
55
- end
56
-
57
- def coerce(other)
58
- case other
59
- when Numeric
60
- [-d, d]
61
- else
62
- super
63
- end
64
- end
65
-
66
- def to_f
67
- return 0 if @d == 0
68
- if @d > 0
69
- Float::INFINITY
70
- else
71
- -Float::INFINITY
72
- end
73
- end
74
- end
7
+ extend Forwardable
75
8
 
76
9
  JULIAN = Infinity.new
77
10
  GREGORIAN = -Infinity.new
@@ -85,6 +18,7 @@ class Date
85
18
  class << self
86
19
  def wrap(native)
87
20
  instance = allocate
21
+ `#{instance}.start = #{ITALY}`
88
22
  `#{instance}.date = #{native}`
89
23
  instance
90
24
  end
@@ -354,73 +288,12 @@ class Date
354
288
  day = 4;
355
289
  }
356
290
  }
357
- @date = `new Date(year, month - 1, day)`
358
- end
359
291
 
360
- def -(date)
361
- %x{
362
- if (date.$$is_number) {
363
- var result = #{clone};
364
- result.date.setDate(#{@date}.getDate() - date);
365
- return result;
366
- }
367
- else if (date.date) {
368
- return Math.round((#{@date} - #{date}.date) / (1000 * 60 * 60 * 24));
369
- }
370
- else {
371
- #{raise TypeError};
372
- }
373
- }
374
- end
375
-
376
- def +(date)
377
- %x{
378
- if (date.$$is_number) {
379
- var result = #{clone};
380
- result.date.setDate(#{@date}.getDate() + date);
381
- return result;
382
- }
383
- else {
384
- #{raise TypeError};
385
- }
386
- }
387
- end
388
-
389
- def <(other)
390
- %x{
391
- var a = #{@date}, b = #{other}.date;
392
- a.setHours(0, 0, 0, 0);
393
- b.setHours(0, 0, 0, 0);
394
- return a < b;
395
- }
396
- end
397
-
398
- def <=(other)
399
- %x{
400
- var a = #{@date}, b = #{other}.date;
401
- a.setHours(0, 0, 0, 0);
402
- b.setHours(0, 0, 0, 0);
403
- return a <= b;
404
- }
405
- end
406
-
407
- def >(other)
408
- %x{
409
- var a = #{@date}, b = #{other}.date;
410
- a.setHours(0, 0, 0, 0);
411
- b.setHours(0, 0, 0, 0);
412
- return a > b;
413
- }
292
+ @date = `new Date(year, month - 1, day)`
293
+ @start = start
414
294
  end
415
295
 
416
- def >=(other)
417
- %x{
418
- var a = #{@date}, b = #{other}.date;
419
- a.setHours(0, 0, 0, 0);
420
- b.setHours(0, 0, 0, 0);
421
- return a >= b;
422
- }
423
- end
296
+ attr_reader :start
424
297
 
425
298
  def <=>(other)
426
299
  %x{
@@ -428,10 +301,10 @@ class Date
428
301
  return #{jd <=> other}
429
302
  }
430
303
 
431
- if (#{Date === other}) {
304
+ if (#{::Date === other}) {
432
305
  var a = #{@date}, b = #{other}.date;
433
- a.setHours(0, 0, 0, 0);
434
- b.setHours(0, 0, 0, 0);
306
+ if (!Opal.is_a(#{self}, #{::DateTime})) a.setHours(0, 0, 0, 0);
307
+ if (!Opal.is_a(#{other}, #{::DateTime})) b.setHours(0, 0, 0, 0);
435
308
 
436
309
  if (a < b) {
437
310
  return -1;
@@ -449,40 +322,28 @@ class Date
449
322
  end
450
323
 
451
324
  def >>(n)
452
- %x{
453
- if (!n.$$is_number) {
454
- #{raise TypeError};
455
- }
325
+ `if (!n.$$is_number) #{raise ::TypeError}`
456
326
 
457
- var result = #{clone}, date = result.date, cur = date.getDate();
458
- date.setDate(1);
459
- date.setMonth(date.getMonth() + n);
460
- date.setDate(Math.min(cur, days_in_month(date.getFullYear(), date.getMonth())));
461
- return result;
462
- }
327
+ self << -n
463
328
  end
464
329
 
465
330
  def <<(n)
466
- %x{
467
- if (!n.$$is_number) {
468
- #{raise TypeError};
469
- }
331
+ `if (!n.$$is_number) #{raise ::TypeError}`
470
332
 
471
- return #{self >> `-n`};
472
- }
333
+ prev_month(n)
473
334
  end
474
335
 
475
336
  def clone
476
- Date.wrap(`new Date(#{@date}.getTime())`)
337
+ date = Date.wrap(@date.dup)
338
+ `date.start = #{@start}`
339
+ date
477
340
  end
478
341
 
479
- def day
480
- `#{@date}.getDate()`
481
- end
342
+ def_delegators :@date, :sunday?, :monday?, :tuesday?, :wednesday?, :thursday?, :friday?, :saturday?,
343
+ :day, :month, :year, :wday, :yday
482
344
 
483
- def friday?
484
- wday == 5
485
- end
345
+ alias mday day
346
+ alias mon month
486
347
 
487
348
  def jd
488
349
  %x{
@@ -524,56 +385,71 @@ class Date
524
385
  `#{@date} < new Date(1582, 10 - 1, 15, 12)`
525
386
  end
526
387
 
527
- def monday?
528
- wday == 1
529
- end
530
-
531
- def month
532
- `#{@date}.getMonth() + 1`
388
+ def new_start(start)
389
+ new_date = clone
390
+ `new_date.start = start`
391
+ new_date
533
392
  end
534
393
 
535
394
  def next
536
395
  self + 1
537
396
  end
538
397
 
539
- def next_day(n = 1)
540
- self + n
541
- end
542
-
543
- def next_month(n = 1)
398
+ def -(date)
544
399
  %x{
545
- var result = #{clone}, date = result.date, cur = date.getDate();
546
- date.setDate(1);
547
- date.setMonth(date.getMonth() + n);
548
- date.setDate(Math.min(cur, days_in_month(date.getFullYear(), date.getMonth())));
549
- return result;
400
+ if (date.date) {
401
+ return Math.round((#{@date} - #{date}.date) / (1000 * 60 * 60 * 24));
402
+ }
550
403
  }
404
+ prev_day(date)
551
405
  end
552
406
 
553
- def next_year(years = 1)
554
- self.class.new(year + years, month, day)
407
+ def +(date)
408
+ next_day(date)
555
409
  end
556
410
 
557
411
  def prev_day(n = 1)
558
- self - n
412
+ %x{
413
+ if (n.$$is_number) {
414
+ var result = #{clone};
415
+ result.date.setDate(#{@date}.getDate() - n);
416
+ return result;
417
+ }
418
+ else {
419
+ #{raise ::TypeError};
420
+ }
421
+ }
422
+ end
423
+
424
+ def next_day(n = 1)
425
+ `if (!n.$$is_number) #{raise ::TypeError}`
426
+ prev_day(-n)
559
427
  end
560
428
 
561
429
  def prev_month(n = 1)
562
430
  %x{
431
+ if (!n.$$is_number) #{raise ::TypeError}
563
432
  var result = #{clone}, date = result.date, cur = date.getDate();
564
433
  date.setDate(1);
565
434
  date.setMonth(date.getMonth() - n);
566
- date.setDate(Math.min(cur, days_in_month(date.getFullYear(), date.getMonth())));
435
+ date.setDate(Math.min(cur, #{Date._days_in_month(`date.getFullYear()`, `date.getMonth()`)}));
567
436
  return result;
568
437
  }
569
438
  end
570
439
 
440
+ def next_month(n = 1)
441
+ `if (!n.$$is_number) #{raise ::TypeError}`
442
+ prev_month(-n)
443
+ end
444
+
571
445
  def prev_year(years = 1)
446
+ `if (!years.$$is_number) #{raise ::TypeError}`
572
447
  self.class.new(year - years, month, day)
573
448
  end
574
449
 
575
- def saturday?
576
- wday == 6
450
+ def next_year(years = 1)
451
+ `if (!years.$$is_number) #{raise ::TypeError}`
452
+ prev_year(-years)
577
453
  end
578
454
 
579
455
  def strftime(format = '')
@@ -582,18 +458,10 @@ class Date
582
458
  return #{to_s};
583
459
  }
584
460
 
585
- return #{@date}.$strftime(#{format});
461
+ return #{@date.strftime(format)}
586
462
  }
587
463
  end
588
464
 
589
- def sunday?
590
- wday == 0
591
- end
592
-
593
- def thursday?
594
- wday == 4
595
- end
596
-
597
465
  def to_s
598
466
  %x{
599
467
  var d = #{@date}, year = d.getFullYear(), month = d.getMonth() + 1, day = d.getDate();
@@ -607,12 +475,16 @@ class Date
607
475
  Time.new(year, month, day)
608
476
  end
609
477
 
610
- def to_n
611
- @date
478
+ def to_date
479
+ self
480
+ end
481
+
482
+ def to_datetime
483
+ DateTime.new(year, month, day)
612
484
  end
613
485
 
614
- def tuesday?
615
- wday == 2
486
+ def to_n
487
+ @date
616
488
  end
617
489
 
618
490
  def step(limit, step = 1, &block)
@@ -621,7 +493,7 @@ class Date
621
493
  steps = if steps_count * step < 0
622
494
  []
623
495
  elsif steps_count < 0
624
- (0..-steps_count).step(step.abs).map(&:-@) .reverse
496
+ (0..-steps_count).step(step.abs).map(&:-@).reverse
625
497
  else
626
498
  (0..steps_count).step(step.abs)
627
499
  end
@@ -645,18 +517,6 @@ class Date
645
517
  step(min, -1, &block)
646
518
  end
647
519
 
648
- def wday
649
- `#{@date}.getDay()`
650
- end
651
-
652
- def wednesday?
653
- wday == 3
654
- end
655
-
656
- def year
657
- `#{@date}.getFullYear()`
658
- end
659
-
660
520
  def cwday
661
521
  `#{@date}.getDay() || 7`
662
522
  end
@@ -670,13 +530,16 @@ class Date
670
530
  }
671
531
  end
672
532
 
673
- %x{
674
- function days_in_month(year, month) {
533
+ def self._days_in_month(year, month)
534
+ %x{
675
535
  var leap = ((year % 4 === 0 && year % 100 !== 0) || year % 400 === 0);
676
- return [31, (leap ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month]
536
+ return [31, (leap ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month];
677
537
  }
678
- }
538
+ end
679
539
 
680
540
  alias eql? ==
681
541
  alias succ next
682
542
  end
543
+
544
+ require 'date/date_time'
545
+ require 'date/formatters'
@@ -1,5 +1,5 @@
1
1
  require 'opal/platform'
2
- require 'opal/replutils'
2
+ require 'opal-replutils'
3
3
  require 'json'
4
4
 
5
5
  REPLUtils.js_repl
@@ -43,7 +43,7 @@ module REPLUtils
43
43
  out
44
44
  end
45
45
 
46
- def eval_and_print(func, mode, colorize)
46
+ def eval_and_print(func, mode, colorize, binding = nil)
47
47
  printer = if colorize
48
48
  ->(i) do
49
49
  ColorPrinter.default(i)
@@ -61,11 +61,11 @@ module REPLUtils
61
61
  end
62
62
 
63
63
  %x{
64
- var $_result = eval(func);
64
+ var $_result = binding === nil ? eval(func) : binding.$js_eval(func);
65
65
 
66
66
  if (mode == 'silent') return nil;
67
67
 
68
- if (typeof $_result === 'null') {
68
+ if ($_result === null) {
69
69
  return "=> null";
70
70
  }
71
71
  else if (typeof $_result === 'undefined') {
data/stdlib/time.rb CHANGED
@@ -3,7 +3,44 @@ class Time
3
3
  `new Date(Date.parse(str))`
4
4
  end
5
5
 
6
- def iso8601
7
- strftime('%FT%T%z')
6
+ def self.def_formatter(name, format, on_utc: false, utc_tz: nil, tz_format: nil, fractions: false, on: self)
7
+ on.define_method name do |fdigits = 0|
8
+ case self
9
+ when defined?(::DateTime) && ::DateTime
10
+ date = on_utc ? new_offset(0) : self
11
+ when defined?(::Date) && ::Date
12
+ date = ::Time.utc(year, month, day)
13
+ when ::Time
14
+ date = on_utc ? getutc : self
15
+ end
16
+ str = date.strftime(format)
17
+ str += date.strftime(".%#{fdigits}N") if fractions && fdigits > 0
18
+ if utc_tz
19
+ str += utc ? utc_tz : date.strftime(tz_format)
20
+ elsif tz_format
21
+ str += date.strftime(tz_format)
22
+ end
23
+ str
24
+ end
25
+ end
26
+
27
+ def_formatter :rfc2822, '%a, %d %b %Y %T ', utc_tz: '-00:00', tz_format: '%z'
28
+ alias rfc822 rfc2822
29
+ def_formatter :httpdate, '%a, %d %b %Y %T GMT', on_utc: true
30
+ def_formatter :xmlschema, '%FT%T', utc_tz: 'Z', tz_format: '%:z', fractions: true
31
+ alias iso8601 xmlschema
32
+
33
+ def to_date
34
+ Date.wrap(self)
35
+ end
36
+
37
+ def to_datetime
38
+ DateTime.wrap(self)
39
+ end
40
+
41
+ def to_time
42
+ self
8
43
  end
9
44
  end
45
+
46
+ require 'date'
data/stdlib/uri.rb ADDED
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module URI
4
+ def self.decode_www_form(str, enc = undefined, separator: '&', use__charset_: false, isindex: false)
5
+ raise ArgumentError, "the input of #{name}.#{__method__} must be ASCII only string" unless str.ascii_only?
6
+
7
+ %x{
8
+ var ary = [], key, val;
9
+ if (str.length == 0)
10
+ return ary;
11
+ if (enc)
12
+ #{enc = Encoding.find(enc)};
13
+
14
+ var parts = str.split(#{separator});
15
+ for (var i = 0; i < parts.length; i++) {
16
+ var string = parts[i];
17
+ var splitIndex = string.indexOf('=')
18
+
19
+ if (splitIndex >= 0) {
20
+ key = string.substr(0, splitIndex);
21
+ val = string.substr(splitIndex + 1);
22
+ } else {
23
+ key = string;
24
+ val = '';
25
+ }
26
+
27
+ if (isindex) {
28
+ if (splitIndex < 0) {
29
+ key = '';
30
+ val = string;
31
+ }
32
+ isindex = false;
33
+ }
34
+
35
+ key = decodeURIComponent(key.replace(/\+/g, ' '));
36
+ if (val) {
37
+ val = decodeURIComponent(val.replace(/\+/g, ' '));
38
+ } else {
39
+ val = '';
40
+ }
41
+
42
+ if (enc) {
43
+ key = #{`key`.force_encoding(enc)}
44
+ val = #{`val`.force_encoding(enc)}
45
+ }
46
+
47
+ ary.push([key, val]);
48
+ }
49
+
50
+ return ary;
51
+ }
52
+ end
53
+ end
@@ -1,6 +1,8 @@
1
1
  JAVASCRIPT_IO_MODULE="nodejs" if RUBY_ENGINE == 'opal'
2
2
  require "asciidoctor"
3
- puts Asciidoctor.convert(DATA.read)
3
+ data = DATA.read
4
+ 100.times { Asciidoctor.convert(data) }
5
+ puts Asciidoctor.convert(data)
4
6
 
5
7
  __END__
6
8
  <%= File.read('asciidoctor/benchmark/sample-data/mdbasics.adoc') %>
@@ -27,7 +27,7 @@ klasses = [
27
27
 
28
28
  return (optstatus & (1 << 6)) ? "[INTERPRETED]" : "[COMPILED]";
29
29
  }
30
-
30
+
31
31
  function triggerOptAndGetStatus(fn) {
32
32
  // using try/catch to avoid having to call functions properly
33
33
  try {
@@ -52,6 +52,7 @@ optimization_status = Hash[klasses.map do |klass|
52
52
  methods -= [:product, :exit, :exit!, :at_exit]
53
53
  opt_status = Hash[methods.map do |method|
54
54
  method_func = `#{klass.instance_method(method)}.method`
55
+ method_func = `#{method_func}.$$proxy_target || #{method_func}`
55
56
  [method, `triggerOptAndGetStatus(#{method_func})`]
56
57
  end]
57
58
  by_status_grouped = opt_status.group_by {|method, status| status }
@@ -74,4 +75,4 @@ optimization_status.sort_by {|klass,_| klass.name}.each do |klass, statuses|
74
75
  end
75
76
  end
76
77
 
77
- puts 'done!'
78
+ puts 'done!'