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
@@ -19,3 +19,29 @@ describe 'super without explicit argument' do
19
19
  klass.new.test_rest_kwargs(native: 4).should == {native: 4}
20
20
  end
21
21
  end
22
+
23
+ class ABlockWithSuperSpec
24
+ BLOCK = proc {
25
+ return [self, super()]
26
+ }
27
+ def foo; :foo; end
28
+ def bar; :bar; end
29
+ def foo_bar; [foo, bar]; end
30
+ end
31
+
32
+ describe "a block with super" do
33
+ it "can be used to define multiple methods" do
34
+ block = nil
35
+
36
+ c = Class.new(ABlockWithSuperSpec) {
37
+ define_method :foo, ABlockWithSuperSpec::BLOCK
38
+ define_method :bar, ABlockWithSuperSpec::BLOCK
39
+ define_method :foo_bar, ABlockWithSuperSpec::BLOCK
40
+ }
41
+
42
+ obj = c.new
43
+ obj.foo.should == [obj, :foo]
44
+ obj.bar.should == [obj, :bar]
45
+ obj.foo_bar.should == [obj, [[obj, :foo], [obj, :bar]]]
46
+ end
47
+ end
@@ -0,0 +1,19 @@
1
+ describe 'Regexp assertions' do
2
+ it 'matches the beginning of input' do
3
+ /\Atext/.should =~ 'text'
4
+ /\Atext/.should_not =~ 'the text'
5
+
6
+ regexp = Regexp.new('\Atext')
7
+ regexp.should =~ 'text'
8
+ regexp.should_not =~ 'the text'
9
+ end
10
+
11
+ it 'matches the end of input' do
12
+ /text\z/.should =~ 'the text'
13
+ /text\z/.should_not =~ 'text of'
14
+
15
+ regexp = Regexp.new('text\z')
16
+ regexp.should =~ 'the text'
17
+ regexp.should_not =~ 'text of'
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Symbol#to_proc" do
4
+ # bug #2417
5
+ it "correctly passes method name to #method_missing" do
6
+ obj = Object.new
7
+ def obj.method_missing(*args); args; end;
8
+ result = :a.to_proc.call(obj, 6, 7)
9
+ result.should == [:a, 6, 7]
10
+ end
11
+
12
+ it "correctly passes a block to #method_missing" do
13
+ obj = Object.new
14
+ block = ->{}
15
+ def obj.method_missing(*args, &block); block; end;
16
+ result = :a.to_proc.call(obj, 1, 2, 3, &block)
17
+ result.should == block
18
+ end
19
+ end
data/spec/ruby_specs CHANGED
@@ -176,6 +176,7 @@ ruby/library/base64
176
176
  ruby/library/bigdecimal
177
177
  !ruby/library/bigdecimal/util_spec
178
178
  ruby/library/date
179
+ ruby/library/datetime
179
180
  ruby/library/delegate/delegator/send_spec
180
181
  ruby/library/erb/util/h_spec
181
182
  ruby/library/erb/util/html_escape_spec
@@ -203,4 +204,7 @@ ruby/library/singleton
203
204
  ruby/library/stringio/each_line_spec
204
205
  ruby/library/stringio/each_spec
205
206
  ruby/library/stringscanner
207
+
208
+ ruby/library/time
209
+
206
210
  ruby/library/optionparser
@@ -1,13 +1,47 @@
1
1
  module RewritersHelper
2
- def s(type, *children)
3
- ::Opal::AST::Node.new(type, children)
2
+ module Common
3
+ def s(type, *children)
4
+ ::Opal::AST::Node.new(type, children)
5
+ end
6
+
7
+ def parse(source)
8
+ buffer = Opal::Parser::SourceBuffer.new('(eval)')
9
+ buffer.source = source
10
+ parser = Opal::Parser.default_parser
11
+ parser.parse(buffer)
12
+ end
13
+
14
+ # Parse, but drop the :top node
15
+ def ast_of(source)
16
+ parse(source).children.first
17
+ end
18
+ end
19
+
20
+ module DSL
21
+ def use_only_described_rewriter!
22
+ around(:each) do |e|
23
+ Opal::Rewriter.disable(except: described_class) { e.run }
24
+ end
25
+ end
26
+ end
27
+
28
+ include Common
29
+
30
+ def self.included(klass)
31
+ klass.extend(Common)
32
+ klass.extend(DSL)
33
+ end
34
+
35
+ def rewriter
36
+ described_class.new
4
37
  end
5
38
 
6
- def rewritten(ast)
7
- described_class.new.process(ast)
39
+ def rewritten(ast = input)
40
+ rewriter.process(ast)
8
41
  end
9
42
 
10
- alias :rewrite :rewritten
43
+ alias rewrite rewritten
44
+ alias processed rewritten
11
45
 
12
46
  def expect_rewritten(ast)
13
47
  expect(rewritten(ast))
@@ -17,28 +51,15 @@ module RewritersHelper
17
51
  expect_rewritten(ast).to eq(ast)
18
52
  end
19
53
 
20
- def parse(source)
21
- buffer = Opal::Parser::SourceBuffer.new('(eval)')
22
- buffer.source = source
23
- parser = Opal::Parser.default_parser
24
- parser.parse(buffer)
25
- end
26
-
27
- alias :ast_of :parse
28
-
29
54
  def parse_without_rewriting(source)
30
- buffer = Opal::Parser::SourceBuffer.new('(eval)')
31
- buffer.source = source
32
- parser = Parser::Ruby31.new
33
- parser.parse(buffer)
55
+ Opal::Rewriter.disable { parse(source) }
34
56
  end
35
57
  end
36
58
 
37
59
  RSpec.shared_examples 'it rewrites source-to-source' do |from_source, to_source|
38
60
  it "rewrites source #{from_source} to source #{to_source}" do
39
- initial = ast_of(from_source)
40
- rewritten = self.rewritten(initial)
41
- expected = ast_of(to_source)
61
+ rewritten = parse(from_source)
62
+ expected = parse(to_source)
42
63
 
43
64
  expect(rewritten).to eq(expected)
44
65
  end
@@ -46,8 +67,7 @@ end
46
67
 
47
68
  RSpec.shared_examples 'it rewrites source-to-AST' do |from_source, to_ast|
48
69
  it "rewrites source #{from_source} to AST #{to_ast}" do
49
- initial = ast_of(from_source)
50
- rewritten = self.rewritten(initial)
70
+ rewritten = parse(from_source).children.first
51
71
 
52
72
  expect(rewritten).to eq(to_ast)
53
73
  end
@@ -0,0 +1,71 @@
1
+ class DateTime < Date
2
+ class << self
3
+ def now
4
+ wrap Time.now
5
+ end
6
+
7
+ def parse(str)
8
+ wrap Time.parse(str)
9
+ end
10
+ end
11
+
12
+ def initialize(year = -4712, month = 1, day = 1, hours = 0, minutes = 0, seconds = 0, offset = 0, start = ITALY)
13
+ %x{
14
+ // Because of Gregorian reform calendar goes from 1582-10-04 to 1582-10-15.
15
+ // All days in between end up as 4 october.
16
+ if (year === 1582 && month === 10 && day > 4 && day < 15) {
17
+ day = 4;
18
+ }
19
+ }
20
+
21
+ @date = Time.new(year, month, day, hours, minutes, seconds, offset)
22
+ @start = start
23
+ end
24
+
25
+ def_delegators :@date, :min, :hour, :sec
26
+ alias minute min
27
+ alias second sec
28
+
29
+ def sec_fraction
30
+ @date.usec / 1_000_000r
31
+ end
32
+
33
+ alias second_fraction sec_fraction
34
+
35
+ def offset
36
+ @date.gmt_offset / (24 * 3600r)
37
+ end
38
+
39
+ def +(other)
40
+ ::DateTime.wrap @date + other
41
+ end
42
+
43
+ def -(other)
44
+ `if (Opal.is_a(other, #{::Date})) other = other.date`
45
+ result = @date - other
46
+ if result.is_a? ::Time
47
+ ::DateTime.wrap result
48
+ else
49
+ result
50
+ end
51
+ end
52
+
53
+ def new_offset(offset)
54
+ new_date = clone
55
+ offset = Time._parse_offset(offset)
56
+ `new_date.date.timezone = offset`
57
+ new_date
58
+ end
59
+
60
+ def to_datetime
61
+ self
62
+ end
63
+
64
+ def to_time
65
+ @date.dup
66
+ end
67
+
68
+ def to_date
69
+ Date.new(year, month, day)
70
+ end
71
+ end
@@ -0,0 +1,28 @@
1
+ class Date
2
+ def self.def_formatter(*args, **kwargs)
3
+ Time.def_formatter(*args, **kwargs, on: self)
4
+ end
5
+
6
+ def_formatter :asctime, '%c'
7
+ alias ctime asctime
8
+ def_formatter :iso8601, '%F'
9
+ alias xmlschema iso8601
10
+ def_formatter :rfc3339, '%FT%T%:z'
11
+ def_formatter :rfc2822, '%a, %-d %b %Y %T %z'
12
+ alias rfc822 rfc2822
13
+ def_formatter :httpdate, '%a, %d %b %Y %T GMT', utc: true
14
+ def_formatter :jisx0301, '%J'
15
+
16
+ alias to_s iso8601
17
+ end
18
+
19
+ class DateTime < Date
20
+ def_formatter :xmlschema, '%FT%T', fractions: true, tz_format: '%:z'
21
+ alias iso8601 xmlschema
22
+ alias rfc3339 xmlschema
23
+ def_formatter :jisx0301, '%JT%T', fractions: true, tz_format: '%:z'
24
+
25
+ alias to_s xmlschema
26
+
27
+ def_formatter :zone, '%:z'
28
+ end
@@ -0,0 +1,73 @@
1
+ class Date
2
+ class Infinity < Numeric
3
+ include Comparable
4
+
5
+ def initialize(d = 1)
6
+ @d = d <=> 0
7
+ end
8
+
9
+ attr_reader :d
10
+
11
+ def zero?
12
+ false
13
+ end
14
+
15
+ def finite?
16
+ false
17
+ end
18
+
19
+ def infinite?
20
+ d.nonzero?
21
+ end
22
+
23
+ def nan?
24
+ d.zero?
25
+ end
26
+
27
+ def abs
28
+ self.class.new
29
+ end
30
+
31
+ def -@
32
+ self.class.new(-d)
33
+ end
34
+
35
+ def +@
36
+ self.class.new(+d)
37
+ end
38
+
39
+ def <=>(other)
40
+ case other
41
+ when Infinity
42
+ d <=> other.d
43
+ when Numeric
44
+ d
45
+ else
46
+ begin
47
+ l, r = other.coerce(self)
48
+ l <=> r
49
+ rescue NoMethodError
50
+ nil
51
+ end
52
+ end
53
+ end
54
+
55
+ def coerce(other)
56
+ case other
57
+ when Numeric
58
+ [-d, d]
59
+ else
60
+ super
61
+ end
62
+ end
63
+
64
+ def to_f
65
+ return 0 if @d == 0
66
+ if @d > 0
67
+ Float::INFINITY
68
+ else
69
+ -Float::INFINITY
70
+ end
71
+ end
72
+ end
73
+ end