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
@@ -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
- def s(type, *children)
5
- ::Opal::AST::Node.new(type, children)
6
- end
7
-
8
- let(:rewriter) { Opal::Rewriters::BinaryOperatorAssignment.new }
5
+ include RewritersHelper
9
6
 
10
- def parse(source)
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
- around(:each) do |e|
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, parse('recvr.a')), # cached = recvr.a
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
- parse('rhs'))))
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, parse('recvr')), # cached = recvr
97
- s(:if, s(:send, cached, :nil?), # if cached.nil?
98
- s(:nil), # nil
99
- # else
100
- s(:send, cached, :meth=, # 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), # cached.meth +
77
+ s(:send, cached, :meth), # cached.meth +
103
78
  :+,
104
- parse('rhs'))) # rhs
105
- )) # end
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
- def s(type, *children)
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(rewriter.process(block_node)).to eq(iter_node)
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
- def s(type, *children)
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/for_rewriter'
4
4
 
5
5
  RSpec.describe Opal::Rewriters::ForRewriter do
6
6
  include RewritersHelper
7
- extend RewritersHelper
8
7
 
9
8
  before(:each) { Opal::Rewriters::ForRewriter.reset_tmp_counter! }
10
9
 
@@ -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.(parse(<<~ENDDEST))
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.(parse(<<~ENDDEST))
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
- def s(type, *children)
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
- def s(type, *children)
5
- ::Opal::AST::Node.new(type, children)
6
- end
7
-
8
- let(:rewriter) { Opal::Rewriters::LogicalOperatorAssignment.new }
5
+ include RewritersHelper
9
6
 
10
- def parse(source)
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
- around(:each) do |e|
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, parse('recvr.a')), # cached = recvr.a
65
+ s(:lvasgn, cache_tmp_name, ast_of('recvr.a')), # cached = recvr.a
91
66
  s(:or,
92
- s(:send, cached, :b), # cached.b
93
- s(:send, cached, :b=, parse('rhs')))) # cached.b = rhs
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, parse('recvr.a')), # cached = recvr.a
78
+ s(:lvasgn, cache_tmp_name, ast_of('recvr.a')), # cached = recvr.a
104
79
  s(:and,
105
- s(:send, cached, :b), # cached.b
106
- s(:send, cached, :b=, parse('rhs')))) # cached.b = rhs
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, parse('recvr')), # cached = recvr
119
- s(:if, s(:send, cached, :nil?), # if cached.nil?
120
- s(:nil), # nil
121
- # else
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), # cached.meth ||
124
- s(:send, cached, :meth=, parse('rhs'))) # cached.meth = rhs
125
- ) # end
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, parse('recvr')), # cached = recvr
137
- s(:if, s(:send, cached, :nil?), # if cached.nil?
138
- s(:nil), # nil
139
- # else
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), # cached.meth ||
142
- s(:send, cached, :meth=, parse('rhs'))) # cached.meth = rhs
143
- ) # end
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 RewritersHelper
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.(parse(<<~ENDDEST))
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.(parse(<<~ENDDEST))
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
- def s(type, *children)
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) { ast_of(source) }
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) { ast_of(rewritten_source) }
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