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
@@ -1,71 +1,46 @@
|
|
1
1
|
require 'lib/spec_helper'
|
2
|
+
require 'support/rewriters_helper'
|
2
3
|
|
3
4
|
RSpec.describe Opal::Rewriters::BinaryOperatorAssignment do
|
4
|
-
|
5
|
-
::Opal::AST::Node.new(type, children)
|
6
|
-
end
|
7
|
-
|
8
|
-
let(:rewriter) { Opal::Rewriters::BinaryOperatorAssignment.new }
|
5
|
+
include RewritersHelper
|
9
6
|
|
10
|
-
|
11
|
-
parser = Opal::Parser.default_parser
|
12
|
-
buffer = ::Opal::Parser::SourceBuffer.new('(eval)')
|
13
|
-
buffer.source = source
|
14
|
-
parser.parse(buffer)
|
15
|
-
end
|
16
|
-
|
17
|
-
def rewrite(ast)
|
18
|
-
rewriter.process(ast)
|
19
|
-
end
|
7
|
+
use_only_described_rewriter!
|
20
8
|
|
21
|
-
|
22
|
-
Opal::Rewriters::BinaryOperatorAssignment.reset_tmp_counter!
|
23
|
-
Opal::Rewriter.disable { e.run }
|
24
|
-
end
|
9
|
+
before(:each) { Opal::Rewriters::BinaryOperatorAssignment.reset_tmp_counter! }
|
25
10
|
let(:cache_tmp_name) { :$binary_op_recvr_tmp_1 }
|
26
11
|
let(:cached) { s(:js_tmp, cache_tmp_name) }
|
27
12
|
|
28
|
-
shared_examples 'it rewrites' do |from, to|
|
29
|
-
it "rewrites #{from.inspect} to #{to.inspect}" do
|
30
|
-
input = parse(from)
|
31
|
-
rewritten = rewrite(input)
|
32
|
-
expected = parse(to)
|
33
|
-
|
34
|
-
expect(rewritten).to eq(expected)
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
13
|
context 'rewriting or_asgn and and_asgn nodes' do
|
39
14
|
context 'local variable' do
|
40
|
-
include_examples 'it rewrites', 'a = 1; a += 2', 'a = 1; a = a + 2'
|
15
|
+
include_examples 'it rewrites source-to-source', 'a = 1; a += 2', 'a = 1; a = a + 2'
|
41
16
|
end
|
42
17
|
|
43
18
|
context 'instance variable' do
|
44
|
-
include_examples 'it rewrites', '@a += 1', '@a = @a + 1'
|
19
|
+
include_examples 'it rewrites source-to-source', '@a += 1', '@a = @a + 1'
|
45
20
|
end
|
46
21
|
|
47
22
|
context 'constant' do
|
48
|
-
include_examples 'it rewrites', 'CONST += 1', 'CONST = CONST + 1'
|
23
|
+
include_examples 'it rewrites source-to-source', 'CONST += 1', 'CONST = CONST + 1'
|
49
24
|
end
|
50
25
|
|
51
26
|
context 'global variable' do
|
52
|
-
include_examples 'it rewrites', '$g += 1', '$g = $g + 1'
|
27
|
+
include_examples 'it rewrites source-to-source', '$g += 1', '$g = $g + 1'
|
53
28
|
end
|
54
29
|
|
55
30
|
context 'class variable' do
|
56
|
-
include_examples 'it rewrites', '@@a += 1', '@@a = @@a + 1'
|
31
|
+
include_examples 'it rewrites source-to-source', '@@a += 1', '@@a = @@a + 1'
|
57
32
|
end
|
58
33
|
|
59
34
|
context 'simple method call' do
|
60
|
-
include_examples 'it rewrites', 'recvr = 1; recvr.meth += rhs', 'recvr = 1; recvr.meth = recvr.meth + rhs'
|
35
|
+
include_examples 'it rewrites source-to-source', 'recvr = 1; recvr.meth += rhs', 'recvr = 1; recvr.meth = recvr.meth + rhs'
|
61
36
|
end
|
62
37
|
|
63
38
|
context '[] / []= method call' do
|
64
|
-
include_examples 'it rewrites', 'recvr = 1; recvr[idx] += rhs', 'recvr = 1; recvr[idx] = recvr[idx] + rhs'
|
39
|
+
include_examples 'it rewrites source-to-source', 'recvr = 1; recvr[idx] += rhs', 'recvr = 1; recvr[idx] = recvr[idx] + rhs'
|
65
40
|
end
|
66
41
|
|
67
42
|
context '[] / []= method call with multiple arguments' do
|
68
|
-
include_examples 'it rewrites',
|
43
|
+
include_examples 'it rewrites source-to-source',
|
69
44
|
'recvr = 1; recvr[idx1, idx2] += rhs',
|
70
45
|
'recvr = 1; recvr[idx1, idx2] = recvr[idx1, idx2] + rhs'
|
71
46
|
end
|
@@ -73,15 +48,15 @@ RSpec.describe Opal::Rewriters::BinaryOperatorAssignment do
|
|
73
48
|
context 'chain of method calls' do
|
74
49
|
it 'rewrites += by caching receiver to a temporary local variable' do
|
75
50
|
input = parse('recvr.a.b += rhs')
|
76
|
-
rewritten = rewrite(input)
|
51
|
+
rewritten = rewrite(input).children.first
|
77
52
|
|
78
53
|
expected = s(:begin,
|
79
|
-
s(:lvasgn, cache_tmp_name,
|
54
|
+
s(:lvasgn, cache_tmp_name, ast_of('recvr.a')), # cached = recvr.a
|
80
55
|
s(:send, cached, :b=,
|
81
56
|
s(:send,
|
82
57
|
s(:send, cached, :b),
|
83
58
|
:+,
|
84
|
-
|
59
|
+
ast_of('rhs'))))
|
85
60
|
|
86
61
|
expect(rewritten).to eq(expected)
|
87
62
|
end
|
@@ -90,19 +65,19 @@ RSpec.describe Opal::Rewriters::BinaryOperatorAssignment do
|
|
90
65
|
context 'method call using safe nafigator' do
|
91
66
|
it 'rewrites += by caching receiver and rewriting it to if and or_asgn' do
|
92
67
|
input = parse('recvr&.meth += rhs')
|
93
|
-
rewritten = rewrite(input)
|
68
|
+
rewritten = rewrite(input).children.first
|
94
69
|
|
95
70
|
expected = s(:begin,
|
96
|
-
s(:lvasgn, cache_tmp_name,
|
97
|
-
s(:if, s(:send, cached, :nil?),
|
98
|
-
s(:nil),
|
99
|
-
|
100
|
-
s(:send, cached, :meth=,
|
71
|
+
s(:lvasgn, cache_tmp_name, ast_of('recvr')), # cached = recvr
|
72
|
+
s(:if, s(:send, cached, :nil?), # if cached.nil?
|
73
|
+
s(:nil), # nil
|
74
|
+
# else
|
75
|
+
s(:send, cached, :meth=, # cached.meth =
|
101
76
|
s(:send,
|
102
|
-
s(:send, cached, :meth),
|
77
|
+
s(:send, cached, :meth), # cached.meth +
|
103
78
|
:+,
|
104
|
-
|
105
|
-
))
|
79
|
+
ast_of('rhs'))) # rhs
|
80
|
+
)) # end
|
106
81
|
|
107
82
|
expect(rewritten).to eq(expected)
|
108
83
|
end
|
@@ -111,43 +86,43 @@ RSpec.describe Opal::Rewriters::BinaryOperatorAssignment do
|
|
111
86
|
|
112
87
|
context 'rewriting defined?(or_asgn) and defined?(and_asgn)' do
|
113
88
|
context 'local variable' do
|
114
|
-
include_examples 'it rewrites', 'a = nil; defined?(a += 1)', 'a = nil; "assignment"'
|
89
|
+
include_examples 'it rewrites source-to-source', 'a = nil; defined?(a += 1)', 'a = nil; "assignment"'
|
115
90
|
end
|
116
91
|
|
117
92
|
context 'instance variable' do
|
118
|
-
include_examples 'it rewrites', 'defined?(@a += 1)', %q("assignment")
|
93
|
+
include_examples 'it rewrites source-to-source', 'defined?(@a += 1)', %q("assignment")
|
119
94
|
end
|
120
95
|
|
121
96
|
context 'constant' do
|
122
|
-
include_examples 'it rewrites', 'defined?(CONST += 1)', %q("assignment")
|
97
|
+
include_examples 'it rewrites source-to-source', 'defined?(CONST += 1)', %q("assignment")
|
123
98
|
end
|
124
99
|
|
125
100
|
context 'global variable' do
|
126
|
-
include_examples 'it rewrites', 'defined?($g += 1)', %q("assignment")
|
101
|
+
include_examples 'it rewrites source-to-source', 'defined?($g += 1)', %q("assignment")
|
127
102
|
end
|
128
103
|
|
129
104
|
context 'class variable' do
|
130
|
-
include_examples 'it rewrites', 'defined?(@@a += 1)', %q("assignment")
|
105
|
+
include_examples 'it rewrites source-to-source', 'defined?(@@a += 1)', %q("assignment")
|
131
106
|
end
|
132
107
|
|
133
108
|
context 'simple method call' do
|
134
|
-
include_examples 'it rewrites', 'defined?(recvr.meth += rhs)', %q("assignment")
|
109
|
+
include_examples 'it rewrites source-to-source', 'defined?(recvr.meth += rhs)', %q("assignment")
|
135
110
|
end
|
136
111
|
|
137
112
|
context '[] / []= method call' do
|
138
|
-
include_examples 'it rewrites', 'defined?(recvr[idx] += rhs)', %q("assignment")
|
113
|
+
include_examples 'it rewrites source-to-source', 'defined?(recvr[idx] += rhs)', %q("assignment")
|
139
114
|
end
|
140
115
|
|
141
116
|
context '[] / []= method call with multiple arguments' do
|
142
|
-
include_examples 'it rewrites', 'defined?(recvr[idx1, idx2] += rhs)', %q("assignment")
|
117
|
+
include_examples 'it rewrites source-to-source', 'defined?(recvr[idx1, idx2] += rhs)', %q("assignment")
|
143
118
|
end
|
144
119
|
|
145
120
|
context 'chain of method calls' do
|
146
|
-
include_examples 'it rewrites', 'defined?(recvr.a.b.c += rhs)', %q("assignment")
|
121
|
+
include_examples 'it rewrites source-to-source', 'defined?(recvr.a.b.c += rhs)', %q("assignment")
|
147
122
|
end
|
148
123
|
|
149
124
|
context 'method call using safe nafigator' do
|
150
|
-
include_examples 'it rewrites', 'defined?(recvr&.meth += rhs)', %q("assignment")
|
125
|
+
include_examples 'it rewrites source-to-source', 'defined?(recvr&.meth += rhs)', %q("assignment")
|
151
126
|
end
|
152
127
|
end
|
153
128
|
end
|
@@ -1,11 +1,8 @@
|
|
1
1
|
require 'lib/spec_helper'
|
2
|
+
require 'support/rewriters_helper'
|
2
3
|
|
3
4
|
RSpec.describe Opal::Rewriters::BlockToIter do
|
4
|
-
|
5
|
-
::Opal::AST::Node.new(type, children)
|
6
|
-
end
|
7
|
-
|
8
|
-
let(:rewriter) { Opal::Rewriters::BlockToIter.new }
|
5
|
+
include RewritersHelper
|
9
6
|
|
10
7
|
let(:block_node) do
|
11
8
|
# m { |arg1| 1 }
|
@@ -23,6 +20,6 @@ RSpec.describe Opal::Rewriters::BlockToIter do
|
|
23
20
|
end
|
24
21
|
|
25
22
|
it 'rewriters s(:block) to s(:iter)' do
|
26
|
-
expect(
|
23
|
+
expect(rewritten(block_node)).to eq(iter_node)
|
27
24
|
end
|
28
25
|
end
|
@@ -1,11 +1,8 @@
|
|
1
1
|
require 'lib/spec_helper'
|
2
|
+
require 'support/rewriters_helper'
|
2
3
|
|
3
4
|
RSpec.describe Opal::Rewriters::DotJsSyntax do
|
4
|
-
|
5
|
-
::Opal::AST::Node.new(type, children)
|
6
|
-
end
|
7
|
-
|
8
|
-
let(:rewriter) { Opal::Rewriters::DotJsSyntax.new }
|
5
|
+
include RewritersHelper
|
9
6
|
|
10
7
|
context '.JS. syntax' do
|
11
8
|
let(:send_node) do
|
@@ -4,7 +4,6 @@ require 'opal/rewriters/forward_args'
|
|
4
4
|
|
5
5
|
RSpec.describe Opal::Rewriters::ForwardArgs do
|
6
6
|
include RewritersHelper
|
7
|
-
extend RewritersHelper
|
8
7
|
|
9
8
|
before(:each) { Opal::Rewriters::ForRewriter.reset_tmp_counter! }
|
10
9
|
|
@@ -23,7 +22,7 @@ RSpec.describe Opal::Rewriters::ForwardArgs do
|
|
23
22
|
end
|
24
23
|
end
|
25
24
|
|
26
|
-
include_examples 'it rewrites source-to-AST', <<~ENDSOURCE, correct_names.(
|
25
|
+
include_examples 'it rewrites source-to-AST', <<~ENDSOURCE, correct_names.(ast_of(<<~ENDDEST))
|
27
26
|
def forward(...)
|
28
27
|
other(...)
|
29
28
|
end
|
@@ -33,7 +32,7 @@ RSpec.describe Opal::Rewriters::ForwardArgs do
|
|
33
32
|
end
|
34
33
|
ENDDEST
|
35
34
|
|
36
|
-
include_examples 'it rewrites source-to-AST', <<~ENDSOURCE, correct_names.(
|
35
|
+
include_examples 'it rewrites source-to-AST', <<~ENDSOURCE, correct_names.(ast_of(<<~ENDDEST))
|
37
36
|
def forward(first_arg, ...)
|
38
37
|
other(first_arg, second_arg, ...)
|
39
38
|
other(other_arg, ...)
|
@@ -1,21 +1,8 @@
|
|
1
1
|
require 'lib/spec_helper'
|
2
|
+
require 'support/rewriters_helper'
|
2
3
|
|
3
4
|
RSpec.describe Opal::Rewriters::JsReservedWords do
|
4
|
-
|
5
|
-
::Opal::AST::Node.new(type, children)
|
6
|
-
end
|
7
|
-
|
8
|
-
def rewrite(sexp)
|
9
|
-
Opal::Rewriters::JsReservedWords.new.process(sexp)
|
10
|
-
end
|
11
|
-
|
12
|
-
def expect_rewritten(sexp)
|
13
|
-
expect(rewrite(sexp))
|
14
|
-
end
|
15
|
-
|
16
|
-
def expect_no_rewriting_for(sexp)
|
17
|
-
expect_rewritten(sexp).to eq(sexp)
|
18
|
-
end
|
5
|
+
include RewritersHelper
|
19
6
|
|
20
7
|
reserved_lvars = %i(
|
21
8
|
do if in for let new try var case else enum eval false
|
@@ -1,82 +1,57 @@
|
|
1
1
|
require 'lib/spec_helper'
|
2
|
+
require 'support/rewriters_helper'
|
2
3
|
|
3
4
|
RSpec.describe Opal::Rewriters::LogicalOperatorAssignment do
|
4
|
-
|
5
|
-
::Opal::AST::Node.new(type, children)
|
6
|
-
end
|
7
|
-
|
8
|
-
let(:rewriter) { Opal::Rewriters::LogicalOperatorAssignment.new }
|
5
|
+
include RewritersHelper
|
9
6
|
|
10
|
-
|
11
|
-
parser = Opal::Parser.default_parser
|
12
|
-
buffer = ::Opal::Parser::SourceBuffer.new('(eval)')
|
13
|
-
buffer.source = source
|
14
|
-
parser.parse(buffer)
|
15
|
-
end
|
16
|
-
|
17
|
-
def rewrite(ast)
|
18
|
-
rewriter.process(ast)
|
19
|
-
end
|
7
|
+
use_only_described_rewriter!
|
20
8
|
|
21
|
-
|
22
|
-
Opal::Rewriters::LogicalOperatorAssignment.reset_tmp_counter!
|
23
|
-
Opal::Rewriter.disable { e.run }
|
24
|
-
end
|
9
|
+
before(:each) { Opal::Rewriters::LogicalOperatorAssignment.reset_tmp_counter! }
|
25
10
|
let(:cache_tmp_name) { :$logical_op_recvr_tmp_1 }
|
26
11
|
let(:cached) { s(:js_tmp, cache_tmp_name) }
|
27
12
|
|
28
|
-
shared_examples 'it rewrites' do |from, to|
|
29
|
-
it "rewrites #{from.inspect} to #{to.inspect}" do
|
30
|
-
input = parse(from)
|
31
|
-
rewritten = rewrite(input)
|
32
|
-
expected = parse(to)
|
33
|
-
|
34
|
-
expect(rewritten).to eq(expected)
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
13
|
context 'rewriting or_asgn and and_asgn nodes' do
|
39
14
|
context 'local variable' do
|
40
|
-
include_examples 'it rewrites', 'a = local; a ||= 1', 'a = local; a = a || 1'
|
41
|
-
include_examples 'it rewrites', 'a = local; a &&= 1', 'a = local; a = a && 1'
|
15
|
+
include_examples 'it rewrites source-to-source', 'a = local; a ||= 1', 'a = local; a = a || 1'
|
16
|
+
include_examples 'it rewrites source-to-source', 'a = local; a &&= 1', 'a = local; a = a && 1'
|
42
17
|
end
|
43
18
|
|
44
19
|
context 'instance variable' do
|
45
|
-
include_examples 'it rewrites', '@a ||= 1', '@a = @a || 1'
|
46
|
-
include_examples 'it rewrites', '@a &&= 1', '@a = @a && 1'
|
20
|
+
include_examples 'it rewrites source-to-source', '@a ||= 1', '@a = @a || 1'
|
21
|
+
include_examples 'it rewrites source-to-source', '@a &&= 1', '@a = @a && 1'
|
47
22
|
end
|
48
23
|
|
49
24
|
context 'constant' do
|
50
|
-
include_examples 'it rewrites', 'CONST ||= 1', 'CONST = defined?(CONST) ? (CONST || 1) : 1'
|
51
|
-
include_examples 'it rewrites', 'CONST &&= 1', 'CONST = CONST && 1'
|
25
|
+
include_examples 'it rewrites source-to-source', 'CONST ||= 1', 'CONST = defined?(CONST) ? (CONST || 1) : 1'
|
26
|
+
include_examples 'it rewrites source-to-source', 'CONST &&= 1', 'CONST = CONST && 1'
|
52
27
|
end
|
53
28
|
|
54
29
|
context 'global variable' do
|
55
|
-
include_examples 'it rewrites', '$g ||= 1', '$g = $g || 1'
|
56
|
-
include_examples 'it rewrites', '$g &&= 1', '$g = $g && 1'
|
30
|
+
include_examples 'it rewrites source-to-source', '$g ||= 1', '$g = $g || 1'
|
31
|
+
include_examples 'it rewrites source-to-source', '$g &&= 1', '$g = $g && 1'
|
57
32
|
end
|
58
33
|
|
59
34
|
context 'class variable' do
|
60
|
-
include_examples 'it rewrites', '@@a ||= 1', '@@a = defined?(@@a) ? (@@a || 1) : 1'
|
61
|
-
include_examples 'it rewrites', '@@a &&= 1', '@@a = @@a && 1'
|
35
|
+
include_examples 'it rewrites source-to-source', '@@a ||= 1', '@@a = defined?(@@a) ? (@@a || 1) : 1'
|
36
|
+
include_examples 'it rewrites source-to-source', '@@a &&= 1', '@@a = @@a && 1'
|
62
37
|
end
|
63
38
|
|
64
39
|
context 'simple method call' do
|
65
|
-
include_examples 'it rewrites', 'recvr = 1; recvr.meth ||= rhs', 'recvr = 1; recvr.meth || recvr.meth = rhs'
|
66
|
-
include_examples 'it rewrites', 'recvr = 1; recvr.meth &&= rhs', 'recvr = 1; recvr.meth && recvr.meth = rhs'
|
40
|
+
include_examples 'it rewrites source-to-source', 'recvr = 1; recvr.meth ||= rhs', 'recvr = 1; recvr.meth || recvr.meth = rhs'
|
41
|
+
include_examples 'it rewrites source-to-source', 'recvr = 1; recvr.meth &&= rhs', 'recvr = 1; recvr.meth && recvr.meth = rhs'
|
67
42
|
end
|
68
43
|
|
69
44
|
context '[] / []= method call' do
|
70
|
-
include_examples 'it rewrites', 'recvr = 1; recvr[idx] ||= rhs', 'recvr = 1; recvr[idx] || recvr[idx] = rhs'
|
71
|
-
include_examples 'it rewrites', 'recvr = 1; recvr[idx] &&= rhs', 'recvr = 1; recvr[idx] && recvr[idx] = rhs'
|
45
|
+
include_examples 'it rewrites source-to-source', 'recvr = 1; recvr[idx] ||= rhs', 'recvr = 1; recvr[idx] || recvr[idx] = rhs'
|
46
|
+
include_examples 'it rewrites source-to-source', 'recvr = 1; recvr[idx] &&= rhs', 'recvr = 1; recvr[idx] && recvr[idx] = rhs'
|
72
47
|
end
|
73
48
|
|
74
49
|
context '[] / []= method call with multiple arguments' do
|
75
|
-
include_examples 'it rewrites',
|
50
|
+
include_examples 'it rewrites source-to-source',
|
76
51
|
'recvr = 1; recvr[idx1, idx2] ||= rhs',
|
77
52
|
'recvr = 1; recvr[idx1, idx2] || recvr[idx1, idx2] = rhs'
|
78
53
|
|
79
|
-
include_examples 'it rewrites',
|
54
|
+
include_examples 'it rewrites source-to-source',
|
80
55
|
'recvr = 1; recvr[idx1, idx2] &&= rhs',
|
81
56
|
'recvr = 1; recvr[idx1, idx2] && recvr[idx1, idx2] = rhs'
|
82
57
|
end
|
@@ -84,26 +59,26 @@ RSpec.describe Opal::Rewriters::LogicalOperatorAssignment do
|
|
84
59
|
context 'chain of method calls' do
|
85
60
|
it 'rewrites ||= by caching receiver to a temporary local variable' do
|
86
61
|
input = parse('recvr.a.b ||= rhs')
|
87
|
-
rewritten = rewrite(input)
|
62
|
+
rewritten = rewrite(input).children.first
|
88
63
|
|
89
64
|
expected = s(:begin,
|
90
|
-
s(:lvasgn, cache_tmp_name,
|
65
|
+
s(:lvasgn, cache_tmp_name, ast_of('recvr.a')), # cached = recvr.a
|
91
66
|
s(:or,
|
92
|
-
s(:send, cached, :b),
|
93
|
-
s(:send, cached, :b=,
|
67
|
+
s(:send, cached, :b), # cached.b ||
|
68
|
+
s(:send, cached, :b=, ast_of('rhs')))) # cached.b = rhs
|
94
69
|
|
95
70
|
expect(rewritten).to eq(expected)
|
96
71
|
end
|
97
72
|
|
98
73
|
it 'rewrites &&= by caching receiver to a temporary local variable' do
|
99
74
|
input = parse('recvr.a.b &&= rhs')
|
100
|
-
rewritten = rewrite(input)
|
75
|
+
rewritten = rewrite(input).children.first
|
101
76
|
|
102
77
|
expected = s(:begin,
|
103
|
-
s(:lvasgn, cache_tmp_name,
|
78
|
+
s(:lvasgn, cache_tmp_name, ast_of('recvr.a')), # cached = recvr.a
|
104
79
|
s(:and,
|
105
|
-
s(:send, cached, :b),
|
106
|
-
s(:send, cached, :b=,
|
80
|
+
s(:send, cached, :b), # cached.b ||
|
81
|
+
s(:send, cached, :b=, ast_of('rhs')))) # cached.b = rhs
|
107
82
|
|
108
83
|
expect(rewritten).to eq(expected)
|
109
84
|
end
|
@@ -112,17 +87,17 @@ RSpec.describe Opal::Rewriters::LogicalOperatorAssignment do
|
|
112
87
|
context 'method call using safe nafigator' do
|
113
88
|
it 'rewrites ||= by caching receiver and rewriting it to if and or_asgn' do
|
114
89
|
input = parse('recvr&.meth ||= rhs')
|
115
|
-
rewritten = rewrite(input)
|
90
|
+
rewritten = rewrite(input).children.first
|
116
91
|
|
117
92
|
expected = s(:begin,
|
118
|
-
s(:lvasgn, cache_tmp_name,
|
119
|
-
s(:if, s(:send, cached, :nil?),
|
120
|
-
s(:nil),
|
121
|
-
|
93
|
+
s(:lvasgn, cache_tmp_name, ast_of('recvr')), # cached = recvr
|
94
|
+
s(:if, s(:send, cached, :nil?), # if cached.nil?
|
95
|
+
s(:nil), # nil
|
96
|
+
# else
|
122
97
|
s(:or,
|
123
|
-
s(:send, cached, :meth),
|
124
|
-
s(:send, cached, :meth=,
|
125
|
-
)
|
98
|
+
s(:send, cached, :meth), # cached.meth ||
|
99
|
+
s(:send, cached, :meth=, ast_of('rhs'))) # cached.meth = rhs
|
100
|
+
) # end
|
126
101
|
)
|
127
102
|
|
128
103
|
expect(rewritten).to eq(expected)
|
@@ -130,17 +105,17 @@ RSpec.describe Opal::Rewriters::LogicalOperatorAssignment do
|
|
130
105
|
|
131
106
|
it 'rewrites &&= by caching receiver and rewriting it to if and or_asgn' do
|
132
107
|
input = parse('recvr&.meth &&= rhs')
|
133
|
-
rewritten = rewrite(input)
|
108
|
+
rewritten = rewrite(input).children.first
|
134
109
|
|
135
110
|
expected = s(:begin,
|
136
|
-
s(:lvasgn, cache_tmp_name,
|
137
|
-
s(:if, s(:send, cached, :nil?),
|
138
|
-
s(:nil),
|
139
|
-
|
111
|
+
s(:lvasgn, cache_tmp_name, ast_of('recvr')), # cached = recvr
|
112
|
+
s(:if, s(:send, cached, :nil?), # if cached.nil?
|
113
|
+
s(:nil), # nil
|
114
|
+
# else
|
140
115
|
s(:and,
|
141
|
-
s(:send, cached, :meth),
|
142
|
-
s(:send, cached, :meth=,
|
143
|
-
)
|
116
|
+
s(:send, cached, :meth), # cached.meth &&
|
117
|
+
s(:send, cached, :meth=, ast_of('rhs'))) # cached.meth = rhs
|
118
|
+
) # end
|
144
119
|
)
|
145
120
|
|
146
121
|
expect(rewritten).to eq(expected)
|
@@ -150,53 +125,53 @@ RSpec.describe Opal::Rewriters::LogicalOperatorAssignment do
|
|
150
125
|
|
151
126
|
context 'rewriting defined?(or_asgn) and defined?(and_asgn)' do
|
152
127
|
context 'local variable' do
|
153
|
-
include_examples 'it rewrites', 'a = nil; defined?(a ||= 1)', 'a = nil; "assignment"'
|
154
|
-
include_examples 'it rewrites', 'a = nil; defined?(a &&= 1)', 'a = nil; "assignment"'
|
128
|
+
include_examples 'it rewrites source-to-source', 'a = nil; defined?(a ||= 1)', 'a = nil; "assignment"'
|
129
|
+
include_examples 'it rewrites source-to-source', 'a = nil; defined?(a &&= 1)', 'a = nil; "assignment"'
|
155
130
|
end
|
156
131
|
|
157
132
|
context 'instance variable' do
|
158
|
-
include_examples 'it rewrites', 'defined?(@a ||= 1)', %q("assignment")
|
159
|
-
include_examples 'it rewrites', 'defined?(@a &&= 1)', %q("assignment")
|
133
|
+
include_examples 'it rewrites source-to-source', 'defined?(@a ||= 1)', %q("assignment")
|
134
|
+
include_examples 'it rewrites source-to-source', 'defined?(@a &&= 1)', %q("assignment")
|
160
135
|
end
|
161
136
|
|
162
137
|
context 'constant' do
|
163
|
-
include_examples 'it rewrites', 'defined?(CONST ||= 1)', %q("assignment")
|
164
|
-
include_examples 'it rewrites', 'defined?(CONST &&= 1)', %q("assignment")
|
138
|
+
include_examples 'it rewrites source-to-source', 'defined?(CONST ||= 1)', %q("assignment")
|
139
|
+
include_examples 'it rewrites source-to-source', 'defined?(CONST &&= 1)', %q("assignment")
|
165
140
|
end
|
166
141
|
|
167
142
|
context 'global variable' do
|
168
|
-
include_examples 'it rewrites', 'defined?($g ||= 1)', %q("assignment")
|
169
|
-
include_examples 'it rewrites', 'defined?($g &&= 1)', %q("assignment")
|
143
|
+
include_examples 'it rewrites source-to-source', 'defined?($g ||= 1)', %q("assignment")
|
144
|
+
include_examples 'it rewrites source-to-source', 'defined?($g &&= 1)', %q("assignment")
|
170
145
|
end
|
171
146
|
|
172
147
|
context 'class variable' do
|
173
|
-
include_examples 'it rewrites', 'defined?(@@a ||= 1)', %q("assignment")
|
174
|
-
include_examples 'it rewrites', 'defined?(@@a &&= 1)', %q("assignment")
|
148
|
+
include_examples 'it rewrites source-to-source', 'defined?(@@a ||= 1)', %q("assignment")
|
149
|
+
include_examples 'it rewrites source-to-source', 'defined?(@@a &&= 1)', %q("assignment")
|
175
150
|
end
|
176
151
|
|
177
152
|
context 'simple method call' do
|
178
|
-
include_examples 'it rewrites', 'defined?(recvr.meth ||= rhs)', %q("assignment")
|
179
|
-
include_examples 'it rewrites', 'defined?(recvr.meth &&= rhs)', %q("assignment")
|
153
|
+
include_examples 'it rewrites source-to-source', 'defined?(recvr.meth ||= rhs)', %q("assignment")
|
154
|
+
include_examples 'it rewrites source-to-source', 'defined?(recvr.meth &&= rhs)', %q("assignment")
|
180
155
|
end
|
181
156
|
|
182
157
|
context '[] / []= method call' do
|
183
|
-
include_examples 'it rewrites', 'defined?(recvr[idx] ||= rhs)', %q("assignment")
|
184
|
-
include_examples 'it rewrites', 'defined?(recvr[idx] &&= rhs)', %q("assignment")
|
158
|
+
include_examples 'it rewrites source-to-source', 'defined?(recvr[idx] ||= rhs)', %q("assignment")
|
159
|
+
include_examples 'it rewrites source-to-source', 'defined?(recvr[idx] &&= rhs)', %q("assignment")
|
185
160
|
end
|
186
161
|
|
187
162
|
context '[] / []= method call with multiple arguments' do
|
188
|
-
include_examples 'it rewrites', 'defined?(recvr[idx1, idx2] ||= rhs)', %q("assignment")
|
189
|
-
include_examples 'it rewrites', 'defined?(recvr[idx1, idx2] &&= rhs)', %q("assignment")
|
163
|
+
include_examples 'it rewrites source-to-source', 'defined?(recvr[idx1, idx2] ||= rhs)', %q("assignment")
|
164
|
+
include_examples 'it rewrites source-to-source', 'defined?(recvr[idx1, idx2] &&= rhs)', %q("assignment")
|
190
165
|
end
|
191
166
|
|
192
167
|
context 'chain of method calls' do
|
193
|
-
include_examples 'it rewrites', 'defined?(recvr.a.b.c ||= rhs)', %q("assignment")
|
194
|
-
include_examples 'it rewrites', 'defined?(recvr.a.b.c &&= rhs)', %q("assignment")
|
168
|
+
include_examples 'it rewrites source-to-source', 'defined?(recvr.a.b.c ||= rhs)', %q("assignment")
|
169
|
+
include_examples 'it rewrites source-to-source', 'defined?(recvr.a.b.c &&= rhs)', %q("assignment")
|
195
170
|
end
|
196
171
|
|
197
172
|
context 'method call using safe nafigator' do
|
198
|
-
include_examples 'it rewrites', 'defined?(recvr&.meth ||= rhs)', %q("assignment")
|
199
|
-
include_examples 'it rewrites', 'defined?(recvr&.meth &&= rhs)', %q("assignment")
|
173
|
+
include_examples 'it rewrites source-to-source', 'defined?(recvr&.meth ||= rhs)', %q("assignment")
|
174
|
+
include_examples 'it rewrites source-to-source', 'defined?(recvr&.meth &&= rhs)', %q("assignment")
|
200
175
|
end
|
201
176
|
end
|
202
177
|
end
|
@@ -4,9 +4,7 @@ require 'opal/rewriters/numblocks'
|
|
4
4
|
|
5
5
|
RSpec.describe Opal::Rewriters::Numblocks do
|
6
6
|
include RewritersHelper
|
7
|
-
extend
|
8
|
-
|
9
|
-
before(:each) { Opal::Rewriters::ForRewriter.reset_tmp_counter! }
|
7
|
+
extend RewritersHelper # s() in example scope
|
10
8
|
|
11
9
|
correct_names = proc do |ast|
|
12
10
|
case ast
|
@@ -22,7 +20,7 @@ RSpec.describe Opal::Rewriters::Numblocks do
|
|
22
20
|
end
|
23
21
|
end
|
24
22
|
|
25
|
-
include_examples 'it rewrites source-to-AST', <<~ENDSOURCE, correct_names.(
|
23
|
+
include_examples 'it rewrites source-to-AST', <<~ENDSOURCE, correct_names.(ast_of(<<~ENDDEST))
|
26
24
|
proc do
|
27
25
|
_1
|
28
26
|
end
|
@@ -32,7 +30,7 @@ RSpec.describe Opal::Rewriters::Numblocks do
|
|
32
30
|
end
|
33
31
|
ENDDEST
|
34
32
|
|
35
|
-
include_examples 'it rewrites source-to-AST', <<~ENDSOURCE, correct_names.(
|
33
|
+
include_examples 'it rewrites source-to-AST', <<~ENDSOURCE, correct_names.(ast_of(<<~ENDDEST))
|
36
34
|
proc do
|
37
35
|
_3
|
38
36
|
end
|
@@ -1,20 +1,8 @@
|
|
1
1
|
require 'lib/spec_helper'
|
2
|
+
require 'support/rewriters_helper'
|
2
3
|
|
3
4
|
RSpec.describe Opal::Rewriters::OpalEngineCheck do
|
4
|
-
|
5
|
-
::Opal::AST::Node.new(type, children)
|
6
|
-
end
|
7
|
-
|
8
|
-
let(:rewriter) { Opal::Rewriters::OpalEngineCheck.new }
|
9
|
-
|
10
|
-
def expect_rewritten(node)
|
11
|
-
processed = rewriter.process(node)
|
12
|
-
expect(processed)
|
13
|
-
end
|
14
|
-
|
15
|
-
def expect_no_rewriting_for(node)
|
16
|
-
expect_rewritten(node).to eq(node)
|
17
|
-
end
|
5
|
+
include RewritersHelper
|
18
6
|
|
19
7
|
let(:opal_str_sexp) { s(:str, 'opal') }
|
20
8
|
let(:true_branch) { s(:int, 1) }
|
@@ -21,7 +21,7 @@ RSpec.describe Opal::Rubyspec::FiltersRewriter do
|
|
21
21
|
SOURCE
|
22
22
|
end
|
23
23
|
|
24
|
-
let(:ast) {
|
24
|
+
let(:ast) { parse(source) }
|
25
25
|
|
26
26
|
context 'when spec is filtered' do
|
27
27
|
around(:each) do |e|
|
@@ -44,16 +44,24 @@ RSpec.describe Opal::Rubyspec::FiltersRewriter do
|
|
44
44
|
SOURCE
|
45
45
|
end
|
46
46
|
|
47
|
-
let(:expected_ast) {
|
47
|
+
let(:expected_ast) { parse(rewritten_source) }
|
48
48
|
|
49
49
|
it 'replaces it with nil' do
|
50
50
|
expect_rewritten(ast).to eq(expected_ast)
|
51
51
|
end
|
52
|
+
|
53
|
+
it 'disables cache' do
|
54
|
+
expect(rewritten(ast).meta[:dynamic_cache_result]).to be_truthy
|
55
|
+
end
|
52
56
|
end
|
53
57
|
|
54
58
|
context 'when spec is not filtered' do
|
55
59
|
it 'does not rewrite it' do
|
56
60
|
expect_no_rewriting_for(ast)
|
57
61
|
end
|
62
|
+
|
63
|
+
it 'disables cache' do
|
64
|
+
expect(rewritten(ast).meta[:dynamic_cache_result]).to be_truthy
|
65
|
+
end
|
58
66
|
end
|
59
67
|
end
|
@@ -33,6 +33,10 @@ describe Opal::Compiler do
|
|
33
33
|
$global["Opal"].irb_vars.bar.should == "HELLO WORLD"
|
34
34
|
end
|
35
35
|
|
36
|
+
it "can reference an outer variable" do
|
37
|
+
eval_js("var a = 10;" + compile("a", :irb => true)).should == 10
|
38
|
+
end
|
39
|
+
|
36
40
|
it "can still call top level methods" do
|
37
41
|
eval_js(compile("to_s", :irb => true)).should == "main"
|
38
42
|
end
|