opal 0.9.0.beta2 → 0.9.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 (104) hide show
  1. checksums.yaml +4 -4
  2. data/.jshintrc +2 -1
  3. data/.travis.yml +8 -4
  4. data/CHANGELOG.md +270 -251
  5. data/CONTRIBUTING.md +41 -0
  6. data/README.md +8 -8
  7. data/Rakefile +1 -1
  8. data/lib/opal/cli.rb +1 -0
  9. data/lib/opal/cli_options.rb +2 -2
  10. data/lib/opal/cli_runners.rb +1 -0
  11. data/lib/opal/cli_runners/nashorn.rb +58 -0
  12. data/lib/opal/cli_runners/phantom.js +11 -9
  13. data/lib/opal/compiler.rb +2 -0
  14. data/lib/opal/erb.rb +2 -1
  15. data/lib/opal/nodes/def.rb +15 -6
  16. data/lib/opal/nodes/helpers.rb +1 -1
  17. data/lib/opal/nodes/literal.rb +1 -1
  18. data/lib/opal/nodes/masgn.rb +79 -29
  19. data/lib/opal/nodes/module.rb +1 -1
  20. data/lib/opal/nodes/top.rb +6 -2
  21. data/lib/opal/parser.rb +1 -0
  22. data/lib/opal/parser/grammar.rb +3160 -3083
  23. data/lib/opal/parser/grammar.y +39 -11
  24. data/lib/opal/parser/lexer.rb +15 -13
  25. data/lib/opal/parser/sexp.rb +5 -0
  26. data/lib/opal/version.rb +1 -1
  27. data/opal/corelib/array.rb +21 -6
  28. data/opal/corelib/basic_object.rb +17 -4
  29. data/opal/corelib/class.rb +1 -1
  30. data/opal/corelib/constants.rb +2 -2
  31. data/opal/corelib/enumerator.rb +2 -0
  32. data/opal/corelib/hash.rb +50 -50
  33. data/opal/corelib/helpers.rb +1 -1
  34. data/opal/corelib/io.rb +9 -6
  35. data/opal/corelib/kernel.rb +37 -9
  36. data/opal/corelib/module.rb +6 -17
  37. data/opal/corelib/nil.rb +4 -0
  38. data/opal/corelib/number.rb +0 -4
  39. data/opal/corelib/runtime.js +637 -662
  40. data/opal/corelib/struct.rb +7 -3
  41. data/spec/filters/bugs/array.rb +4 -9
  42. data/spec/filters/bugs/basicobject.rb +1 -15
  43. data/spec/filters/bugs/date.rb +4 -26
  44. data/spec/filters/bugs/enumerable.rb +26 -1
  45. data/spec/filters/bugs/enumerator.rb +4 -4
  46. data/spec/filters/bugs/exception.rb +1 -7
  47. data/spec/filters/bugs/float.rb +14 -0
  48. data/spec/filters/bugs/hash.rb +0 -2
  49. data/spec/filters/bugs/integer.rb +1 -1
  50. data/spec/filters/bugs/kernel.rb +47 -66
  51. data/spec/filters/bugs/language.rb +1 -2
  52. data/spec/filters/bugs/module.rb +11 -14
  53. data/spec/filters/bugs/numeric.rb +3 -3
  54. data/spec/filters/bugs/proc.rb +0 -1
  55. data/spec/filters/bugs/range.rb +2 -3
  56. data/spec/filters/bugs/regexp.rb +15 -17
  57. data/spec/filters/bugs/set.rb +2 -2
  58. data/spec/filters/bugs/string.rb +29 -5
  59. data/spec/filters/bugs/{strscan.rb → stringscanner.rb} +9 -10
  60. data/spec/filters/bugs/struct.rb +0 -4
  61. data/spec/filters/bugs/time.rb +2 -3
  62. data/spec/filters/bugs/unboundmethod.rb +3 -0
  63. data/spec/filters/unsupported/freeze.rb +2 -1
  64. data/spec/filters/unsupported/taint.rb +2 -0
  65. data/spec/lib/parser/aref_spec.rb +10 -0
  66. data/spec/lib/parser/lambda_spec.rb +14 -0
  67. data/spec/lib/parser/op_asgn_spec.rb +17 -0
  68. data/spec/lib/parser/return_spec.rb +5 -0
  69. data/spec/lib/parser/unary_spec.rb +4 -0
  70. data/spec/lib/sprockets/erb_spec.rb +1 -1
  71. data/spec/mspec/opal/formatters.rb +159 -0
  72. data/{lib → spec}/mspec/opal/runner.rb +0 -160
  73. data/spec/opal/core/hash/internals_spec.rb +162 -162
  74. data/spec/opal/core/kernel/at_exit_spec.rb +70 -0
  75. data/spec/opal/core/kernel/extend_spec.rb +1 -1
  76. data/spec/opal/core/kernel/instance_variables_spec.rb +56 -0
  77. data/spec/opal/core/language/equal_spec.rb +8 -0
  78. data/spec/opal/core/language/predefined_spec.rb +1 -1
  79. data/spec/opal/core/language/ternary_operator_spec.rb +14 -0
  80. data/spec/opal/core/language/versions/{hash_1.9.rb → hash_1_9_spec.rb} +5 -0
  81. data/spec/opal/core/module/fixtures/classes.rb +11 -1
  82. data/spec/opal/core/module/method_lookup_spec.rb +13 -0
  83. data/spec/opal/core/runtime/super_spec.rb +10 -0
  84. data/spec/opal/stdlib/native/new_spec.rb +84 -0
  85. data/spec/opal/stdlib/strscan/scan_spec.rb +11 -0
  86. data/spec/rubyspecs +6 -9
  87. data/spec/spec_helper.rb +9 -21
  88. data/stdlib/date.rb +121 -1
  89. data/stdlib/js.rb +13 -5
  90. data/stdlib/json.rb +3 -3
  91. data/stdlib/nashorn.rb +5 -0
  92. data/stdlib/nashorn/file.rb +13 -0
  93. data/stdlib/nashorn/io.rb +2 -0
  94. data/stdlib/native.rb +12 -4
  95. data/stdlib/nodejs/io.rb +5 -2
  96. data/stdlib/opal/platform.rb +19 -0
  97. data/stdlib/phantomjs.rb +4 -0
  98. data/stdlib/strscan.rb +1 -1
  99. data/tasks/building.rake +2 -1
  100. data/tasks/testing.rake +29 -34
  101. data/tasks/testing/{phantomjs1-sprockets.js → sprockets-phantomjs.js} +2 -20
  102. data/vendored-minitest/minitest/test.rb +7 -15
  103. metadata +32 -9
  104. data/lib/mspec/opal/main.rb.erb +0 -9
@@ -18,5 +18,8 @@ opal_filter "UnboundMethod" do
18
18
  fails "UnboundMethod#source_location sets the last value to a Fixnum representing the line on which the method was defined"
19
19
  fails "UnboundMethod#source_location works for define_method methods"
20
20
  fails "UnboundMethod#source_location works for define_singleton_method methods"
21
+ fails "UnboundMethod#super_method returns nil when the parent's method is removed"
22
+ fails "UnboundMethod#super_method returns nil when there's no super method in the parent"
23
+ fails "UnboundMethod#super_method returns the method that would be called by super in the method"
21
24
  fails "UnboundMethod#to_s the String shows the method name, Module defined in and Module extracted from"
22
25
  end
@@ -5,8 +5,10 @@ opal_filter "freezing" do
5
5
  fails "Array#rotate! raises a RuntimeError on a frozen array"
6
6
  fails "Array#select! on frozen objects returns an Enumerator if no block is given"
7
7
  fails "Array#sort does not freezes self during being sorted"
8
+ fails "Date constants freezes MONTHNAMES, DAYNAMES, ABBR_MONTHNAMES, ABBR_DAYSNAMES"
8
9
  fails "Enumerable#sort doesn't raise an error if #to_a returns a frozen Array"
9
10
  fails "Hash#== compares keys with matching hash codes via eql?"
11
+ fails "Hash#[]= doesn't duplicate and freeze already frozen string keys"
10
12
  fails "Hash#delete_if returns an Enumerator if called on a frozen instance"
11
13
  fails "Hash#each returns an Enumerator if called on a frozen instance"
12
14
  fails "Hash#each_key returns an Enumerator if called on a frozen instance"
@@ -18,7 +20,6 @@ opal_filter "freezing" do
18
20
  fails "Hash#select returns an Enumerator if called on a frozen instance"
19
21
  fails "Hash#select! returns an Enumerator if called on a frozen instance"
20
22
  fails "Hash#store doesn't duplicate and freeze already frozen string keys"
21
- fails "Hash#[]= doesn't duplicate and freeze already frozen string keys"
22
23
  fails "Kernel#clone copies frozen state from the original"
23
24
  fails "Kernel#freeze on a Symbol has no effect since it is already frozen"
24
25
  fails "Kernel#freeze prevents self from being further modified"
@@ -1,4 +1,6 @@
1
1
  opal_filter "taint" do
2
+ fails "Hash#reject with extra state does not taint the resulting hash"
3
+
2
4
  fails "Range#to_s ignores own tainted status"
3
5
  fails "Range#inspect ignores own tainted status"
4
6
 
@@ -0,0 +1,10 @@
1
+ require 'support/parser_helpers'
2
+
3
+ describe "Method calls using receiver[] syntax" do
4
+ it "accepts trailing &block argument" do
5
+ # regression test; see GH issue #959
6
+ splat = [:splat, [:call, nil, :args, [:arglist]]]
7
+ block = [:block_pass, [:call, nil, :block, [:arglist]]]
8
+ parsed("User[*args, &block]").should == [:call, [:const, :User], :[], [:arglist, splat, block]]
9
+ end
10
+ end
@@ -61,4 +61,18 @@ describe "Lambda literals" do
61
61
  parsed("-> { 42; 3.142 }")[4][2].should == [:block, [:int, 42], [:float, 3.142]]
62
62
  end
63
63
  end
64
+
65
+ it "can parse do..end blocks inside lambda body" do
66
+ # regression test; see GH issue 544
67
+ call_b = [:call, nil, :b, [:arglist], [:iter, [:lasgn, :c]]]
68
+ lambda = [:call, nil, :lambda, [:arglist], [:iter, nil, call_b]]
69
+ expected = [:call, nil, :a, [:arglist, lambda]]
70
+ parsed("a -> { b do |c| end }").should == expected
71
+ end
72
+
73
+ it "can parse do..end after lambda body" do
74
+ # regression test; see GH issue 1228
75
+ expected = [:call, nil, :a, [:arglist, [:call, nil, :lambda, [:arglist], [:iter, nil, [:call, nil, :b, [:arglist]]]]], [:iter, nil]]
76
+ parsed("a ->{b} do; end").should == expected
77
+ end
64
78
  end
@@ -0,0 +1,17 @@
1
+ require 'support/parser_helpers'
2
+
3
+ describe "Operator assignment statements on local variables" do
4
+ it "parses |= with a lvar on the left and parenthesized expr on the right" do
5
+ # regression test; see GH issue 995
6
+ asgn = [:lasgn, :var, [:int, 1]]
7
+ opasgn = [:lasgn, :var, [:call, [:lvar, :var], :|, [:arglist, [:paren, [:int, 1]]]]]
8
+ parsed('var = 1; var |= (1)').should == [:block, asgn, opasgn]
9
+ end
10
+
11
+ it "parses >>= with a lvar on the left and parenthesized expr on the right" do
12
+ # regression test; see GH issue 995
13
+ asgn = [:lasgn, :var, [:int, 1]]
14
+ opasgn = [:lasgn, :var, [:call, [:lvar, :var], :>>, [:arglist, [:paren, [:int, 1]]]]]
15
+ parsed('var = 1; var >>= (1)').should == [:block, asgn, opasgn]
16
+ end
17
+ end
@@ -14,4 +14,9 @@ describe "The return keyword" do
14
14
  parsed("return 1, 2").should == [:return, [:array, [:int, 1], [:int, 2]]]
15
15
  parsed("return 1, *2").should == [:return, [:array, [:int, 1], [:splat, [:int, 2]]]]
16
16
  end
17
+
18
+ it "can handle a %{string literal with percent syntax}" do
19
+ # regression test; see GH issue 1089
20
+ parsed("return %{a}").should == [:return, [:str, "a"]]
21
+ end
17
22
  end
@@ -5,6 +5,10 @@ describe Opal::Parser do
5
5
  context 'with an integer' do
6
6
  it "parses unary op. with the right precedence" do
7
7
  parsed("-1.hello").should == [:call, [:int, -1], :hello, [:arglist]]
8
+ expected = [:call, [:call, [:int, 1], :**, [:arglist, [:int, 2]]], :-@, [:arglist]]
9
+ parsed("-1 ** 2").should == expected
10
+ expected = [:call, nil, :puts, [:arglist, [:call, [:int, -1], :hello, [:arglist]]]]
11
+ parsed("puts -1.hello").should == expected
8
12
  end
9
13
 
10
14
  it "parses unary op. as a method call" do
@@ -18,7 +18,7 @@ describe Opal::ERB::Processor do
18
18
  is_a?: true,
19
19
  ) }
20
20
  let(:required_assets) { [] }
21
- let(:template) { described_class.new { |t| %Q{<a href="<%= url %>"><%= name %></a>} } }
21
+ let(:template) { described_class.new { |t| %Q{<% print("") %><a href="<%= url %>"><%= name %></a>} } }
22
22
  before { sprockets_context.stub(:require_asset) {|asset| required_assets << asset } }
23
23
 
24
24
  let(:ext) { 'opalerb' }
@@ -0,0 +1,159 @@
1
+ class BrowserFormatter
2
+ def initialize(out=nil)
3
+ @exception = @failure = false
4
+ @exceptions = []
5
+ @count = 0
6
+ @examples = 0
7
+
8
+ @current_state = nil
9
+ end
10
+
11
+ def register
12
+ MSpec.register :exception, self
13
+ MSpec.register :before, self
14
+ MSpec.register :after, self
15
+ MSpec.register :start, self
16
+ MSpec.register :finish, self
17
+ MSpec.register :abort, self
18
+ MSpec.register :enter, self
19
+ end
20
+
21
+ def green(str)
22
+ `console.info(str)`
23
+ end
24
+
25
+ def red(str)
26
+ `console.error(str)`
27
+ end
28
+
29
+ def log(str)
30
+ `console.log(str)`
31
+ end
32
+
33
+ def exception?
34
+ @exception
35
+ end
36
+
37
+ def failure?
38
+ @failure
39
+ end
40
+
41
+ def enter(describe); end
42
+
43
+ def before(state=nil)
44
+ @current_state = nil
45
+ @failure = @exception = false
46
+ end
47
+
48
+ def exception(exception)
49
+ @count += 1
50
+ @failure = @exception ? @failure && exception.failure? : exception.failure?
51
+ @exception = true
52
+ @exceptions << exception
53
+ end
54
+
55
+ def after(state = nil)
56
+ @current_state = nil
57
+ @examples += 1
58
+ end
59
+
60
+ def start
61
+ @start_time = Time.now.to_f
62
+ end
63
+
64
+ def finish
65
+ time = Time.now.to_f - @start_time
66
+
67
+ if @exceptions.empty?
68
+ log "\nFinished"
69
+ green "#{@examples} examples, #{@count} failures (time taken: #{time})"
70
+
71
+ finish_with_code 0
72
+ else
73
+ log "\nFailures:"
74
+
75
+ @exceptions.each_with_index do |exception, idx|
76
+ log "\n #{idx + 1}. #{exception.description}"
77
+ red "\n #{exception.message}"
78
+ log "\n #{`#{exception.exception}.stack`}\n"
79
+ end
80
+
81
+ log "\nFinished"
82
+ red "#{@examples} examples, #{@count} failures (time taken: #{time})"
83
+
84
+ finish_with_code(1)
85
+ end
86
+ end
87
+
88
+ def finish_with_code(code)
89
+ exit(code)
90
+ end
91
+ end
92
+
93
+ class PhantomFormatter < BrowserFormatter
94
+ def green(str)
95
+ `console.log('\033[32m' + str + '\033[0m')`
96
+ end
97
+
98
+ def red(str)
99
+ `console.log('\033[31m' + str + '\033[0m')`
100
+ end
101
+
102
+ def log(str)
103
+ `console.log(str)`
104
+ end
105
+
106
+ def after(state)
107
+ super
108
+ unless exception?
109
+ print '.'
110
+ else
111
+ print failure? ? 'F' : 'E'
112
+ end
113
+ end
114
+ end
115
+
116
+ class NodeJSFormatter < BrowserFormatter
117
+ def green(str)
118
+ `process.stdout.write("\033[32m"+#{str}+"\033[0m")`
119
+ end
120
+
121
+ def red(str)
122
+ `process.stdout.write("\033[31m"+#{str}+"\033[0m")`
123
+ end
124
+
125
+ def log(str)
126
+ puts str
127
+ end
128
+
129
+ def after(state)
130
+ super
131
+ print_example(state)
132
+ end
133
+
134
+ def print_example(state)
135
+ unless exception?
136
+ green('.')
137
+ else
138
+ red(failure? ? 'F' : 'E')
139
+ end
140
+ end
141
+
142
+ def finish_with_code(code)
143
+ exit(code)
144
+ end
145
+ end
146
+
147
+ class PhantomDocFormatter < PhantomFormatter
148
+ def after(state = nil)
149
+ (@exception && state) ? red(state.description) : green(state.description)
150
+ super
151
+ end
152
+ end
153
+
154
+ class NodeJSDocFormatter < NodeJSFormatter
155
+ def print_example(state)
156
+ (@exception && state) ? red(state.description+"\n") : green(state.description+"\n")
157
+ end
158
+ end
159
+
@@ -78,166 +78,6 @@ class Object
78
78
  end
79
79
  end
80
80
 
81
- class BrowserFormatter
82
- def initialize(out=nil)
83
- @exception = @failure = false
84
- @exceptions = []
85
- @count = 0
86
- @examples = 0
87
-
88
- @current_state = nil
89
- end
90
-
91
- def register
92
- MSpec.register :exception, self
93
- MSpec.register :before, self
94
- MSpec.register :after, self
95
- MSpec.register :start, self
96
- MSpec.register :finish, self
97
- MSpec.register :abort, self
98
- MSpec.register :enter, self
99
- end
100
-
101
- def green(str)
102
- `console.info(str)`
103
- end
104
-
105
- def red(str)
106
- `console.error(str)`
107
- end
108
-
109
- def log(str)
110
- `console.log(str)`
111
- end
112
-
113
- def exception?
114
- @exception
115
- end
116
-
117
- def failure?
118
- @failure
119
- end
120
-
121
- def enter(describe); end
122
-
123
- def before(state=nil)
124
- @current_state = nil
125
- @failure = @exception = false
126
- end
127
-
128
- def exception(exception)
129
- @count += 1
130
- @failure = @exception ? @failure && exception.failure? : exception.failure?
131
- @exception = true
132
- @exceptions << exception
133
- end
134
-
135
- def after(state = nil)
136
- @current_state = nil
137
- @examples += 1
138
- end
139
-
140
- def start
141
- @start_time = Time.now.to_f
142
- end
143
-
144
- def finish
145
- time = Time.now.to_f - @start_time
146
-
147
- if @exceptions.empty?
148
- log "\nFinished"
149
- green "#{@examples} examples, #{@count} failures (time taken: #{time})"
150
-
151
- finish_with_code 0
152
- else
153
- log "\nFailures:"
154
-
155
- @exceptions.each_with_index do |exception, idx|
156
- log "\n #{idx + 1}. #{exception.description}"
157
- red "\n #{exception.message}"
158
- log "\n #{`#{exception.exception}.stack`}\n"
159
- end
160
-
161
- log "\nFinished"
162
- red "#{@examples} examples, #{@count} failures (time taken: #{time})"
163
-
164
- finish_with_code(1)
165
- end
166
- end
167
-
168
- def finish_with_code(code)
169
- `window.OPAL_SPEC_CODE = code;`
170
- end
171
- end
172
-
173
- class PhantomFormatter < BrowserFormatter
174
- def green(str)
175
- `console.log('\033[32m' + str + '\033[0m')`
176
- end
177
-
178
- def red(str)
179
- `console.log('\033[31m' + str + '\033[0m')`
180
- end
181
-
182
- def log(str)
183
- `console.log(str)`
184
- end
185
-
186
- def after(state)
187
- super
188
- unless exception?
189
- print '.'
190
- else
191
- print failure? ? 'F' : 'E'
192
- end
193
- end
194
- end
195
-
196
- class NodeJSFormatter < BrowserFormatter
197
- def green(str)
198
- `process.stdout.write("\033[32m"+#{str}+"\033[0m")`
199
- end
200
-
201
- def red(str)
202
- `process.stdout.write("\033[31m"+#{str}+"\033[0m")`
203
- end
204
-
205
- def log(str)
206
- puts str
207
- end
208
-
209
- def after(state)
210
- super
211
- print_example(state)
212
- end
213
-
214
- def print_example(state)
215
- unless exception?
216
- green('.')
217
- else
218
- red(failure? ? 'F' : 'E')
219
- end
220
- end
221
-
222
- def finish_with_code(code)
223
- puts "\n\n"
224
- exit(code)
225
- end
226
- end
227
-
228
- class PhantomDocFormatter < PhantomFormatter
229
- def after(state = nil)
230
- (@exception && state) ? red(state.description) : green(state.description)
231
- super
232
- end
233
- end
234
-
235
- class NodeJSDocFormatter < NodeJSFormatter
236
- def print_example(state)
237
- (@exception && state) ? red(state.description+"\n") : green(state.description+"\n")
238
- end
239
- end
240
-
241
81
  module MSpec
242
82
  def self.opal_runner
243
83
  @env = Object.new