opal 1.4.1 → 1.5.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
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!'