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.
- 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
|