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.
- checksums.yaml +4 -4
- data/.eslintrc.js +5 -3
- data/.rubocop.yml +1 -0
- data/UNRELEASED.md +37 -2
- data/benchmark-ips/bm_js_symbols_vs_strings.rb +39 -14
- data/docs/releasing.md +10 -2
- data/lib/opal/ast/matcher.rb +77 -0
- data/lib/opal/cache.rb +1 -1
- data/lib/opal/cli_runners/applescript.rb +2 -0
- data/lib/opal/compiler.rb +18 -9
- data/lib/opal/nodes/call.rb +73 -28
- data/lib/opal/nodes/def.rb +31 -27
- data/lib/opal/nodes/definitions.rb +2 -0
- data/lib/opal/nodes/helpers.rb +4 -23
- data/lib/opal/nodes/if.rb +222 -0
- data/lib/opal/nodes/iter.rb +41 -37
- data/lib/opal/nodes/literal.rb +2 -2
- data/lib/opal/nodes/masgn.rb +15 -17
- data/lib/opal/nodes/node_with_args/shortcuts.rb +100 -0
- data/lib/opal/nodes/node_with_args.rb +1 -0
- data/lib/opal/nodes/top.rb +26 -10
- data/lib/opal/nodes.rb +0 -1
- data/lib/opal/parser/default_config.rb +3 -2
- data/lib/opal/repl.rb +1 -1
- data/lib/opal/rewriter.rb +13 -6
- data/lib/opal/rewriters/base.rb +12 -1
- data/lib/opal/rewriters/rubyspec/filters_rewriter.rb +1 -0
- data/lib/opal/version.rb +1 -1
- data/opal/corelib/array.rb +23 -28
- data/opal/corelib/binding.rb +14 -4
- data/opal/corelib/constants.rb +3 -3
- data/opal/corelib/hash.rb +2 -2
- data/opal/corelib/irb.rb +192 -0
- data/opal/corelib/math/polyfills.rb +127 -0
- data/opal/corelib/math.rb +14 -194
- data/opal/corelib/module.rb +23 -25
- data/opal/corelib/number.rb +63 -14
- data/opal/corelib/regexp.rb +2 -0
- data/opal/corelib/runtime.js +56 -20
- data/opal/corelib/string.rb +38 -59
- data/opal/corelib/time.rb +106 -68
- data/opal/opal/full.rb +0 -1
- data/opal/opal.rb +4 -1
- data/spec/filters/bugs/date.rb +0 -3
- data/spec/filters/bugs/datetime.rb +65 -0
- data/spec/filters/bugs/float.rb +0 -18
- data/spec/filters/bugs/hash.rb +0 -2
- data/spec/filters/bugs/language.rb +0 -3
- data/spec/filters/bugs/marshal.rb +0 -1
- data/spec/filters/bugs/string.rb +0 -30
- data/spec/filters/bugs/time.rb +18 -8
- data/spec/lib/cli_spec.rb +2 -2
- data/spec/lib/compiler_spec.rb +8 -8
- data/spec/lib/rewriters/base_spec.rb +1 -1
- data/spec/lib/rewriters/binary_operator_assignment_spec.rb +34 -59
- data/spec/lib/rewriters/block_to_iter_spec.rb +3 -6
- data/spec/lib/rewriters/dot_js_syntax_spec.rb +2 -5
- data/spec/lib/rewriters/for_rewriter_spec.rb +0 -1
- data/spec/lib/rewriters/forward_args_spec.rb +2 -3
- data/spec/lib/rewriters/js_reserved_words_spec.rb +2 -15
- data/spec/lib/rewriters/logical_operator_assignment_spec.rb +64 -89
- data/spec/lib/rewriters/numblocks_spec.rb +3 -5
- data/spec/lib/rewriters/opal_engine_check_spec.rb +2 -14
- data/spec/lib/rewriters/rubyspec/filters_rewriter_spec.rb +10 -2
- data/spec/opal/compiler/irb_spec.rb +4 -0
- data/spec/opal/core/language/super_spec.rb +26 -0
- data/spec/opal/core/regexp/assertions_spec.rb +19 -0
- data/spec/opal/core/string/to_proc_spec.rb +19 -0
- data/spec/ruby_specs +4 -0
- data/spec/support/rewriters_helper.rb +43 -23
- data/stdlib/date/date_time.rb +71 -0
- data/stdlib/date/formatters.rb +28 -0
- data/stdlib/date/infinity.rb +73 -0
- data/stdlib/date.rb +77 -214
- data/stdlib/opal/repl_js.rb +1 -1
- data/stdlib/{opal/replutils.rb → opal-replutils.rb} +3 -3
- data/stdlib/time.rb +39 -2
- data/stdlib/uri.rb +53 -0
- data/tasks/performance/asciidoctor_test.rb.erb +3 -1
- data/tasks/performance/optimization_status.rb +3 -2
- data/tasks/performance.rake +69 -35
- data/tasks/testing.rake +1 -0
- data/test/opal/test_uri.rb +35 -0
- data/yarn.lock +27 -5
- metadata +31 -18
- data/lib/opal/nodes/csend.rb +0 -24
- data/lib/opal/rewriters/explicit_writer_return.rb +0 -59
- data/spec/lib/rewriters/explicit_writer_return_spec.rb +0 -186
- 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
|
-
|
3
|
-
|
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
|
-
|
39
|
+
def rewritten(ast = input)
|
40
|
+
rewriter.process(ast)
|
8
41
|
end
|
9
42
|
|
10
|
-
alias
|
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
|
-
|
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
|
-
|
40
|
-
|
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
|
-
|
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
|