opal 0.3.39 → 0.3.40

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,17 @@
1
+ ## 0.3.40 2013-02-23
2
+
3
+ * Add Opal::Server as an easy to configure rack server for testing and
4
+ running Opal based apps.
5
+
6
+ * Added optional arity check mode for parser. When turned on, every method
7
+ will have code which checks the argument arity. Off by default.
8
+
9
+ * Exception subclasses now relfect their name in webkit/firefox debuggers
10
+ to show both their class name and message.
11
+
12
+ * Add Class#const_set. Trying to access undefined constants by a literal
13
+ constant will now also raise a NameError.
14
+
1
15
  ## 0.3.39 2013-02-20
2
16
 
3
17
  * Fix bug where methods defined on a parent class after subclass was defined
data/Rakefile CHANGED
@@ -4,6 +4,13 @@ Bundler.require
4
4
  require 'opal/spec/rake_task'
5
5
  Opal::Spec::RakeTask.new(:default)
6
6
 
7
+ desc "Run tests with method_missing turned off"
8
+ task :test_no_method_missing do
9
+ # some specs will fail (namely method_missing based specs)
10
+ Opal::Processor.method_missing_enabled = false
11
+ Rake::Task[:default].invoke
12
+ end
13
+
7
14
  desc "Check file sizes for opal.js runtime"
8
15
  task :sizes do
9
16
  o = Opal::Environment.new['opal'].to_s
@@ -8,7 +8,7 @@ class Array < `Array`
8
8
  objects
9
9
  end
10
10
 
11
- def self.new(size, obj = nil, &block)
11
+ def self.new(size = undefined, obj = nil, &block)
12
12
  %x{
13
13
  var arr = [];
14
14
 
@@ -301,7 +301,7 @@ class Array < `Array`
301
301
  self
302
302
  end
303
303
 
304
- def count(object)
304
+ def count(object = undefined)
305
305
  %x{
306
306
  if (object == null) {
307
307
  return #{self}.length;
@@ -380,6 +380,8 @@ class Array < `Array`
380
380
  alias dup clone
381
381
 
382
382
  def each(&block)
383
+ return enum_for :each unless block_given?
384
+
383
385
  `for (var i = 0, length = #{self}.length; i < length; i++) {`
384
386
  yield `#{self}[i]`
385
387
  `}`
@@ -399,7 +401,7 @@ class Array < `Array`
399
401
  `!#{self}.length`
400
402
  end
401
403
 
402
- def fetch(index, defaults, &block)
404
+ def fetch(index, defaults = undefined, &block)
403
405
  %x{
404
406
  var original = index;
405
407
 
@@ -440,7 +442,7 @@ class Array < `Array`
440
442
  self
441
443
  end
442
444
 
443
- def first(count)
445
+ def first(count = undefined)
444
446
  %x{
445
447
  if (count != null) {
446
448
  return #{self}.slice(0, count);
@@ -450,7 +452,7 @@ class Array < `Array`
450
452
  }
451
453
  end
452
454
 
453
- def flatten(level)
455
+ def flatten(level = undefined)
454
456
  %x{
455
457
  var result = [];
456
458
 
@@ -477,7 +479,7 @@ class Array < `Array`
477
479
  }
478
480
  end
479
481
 
480
- def flatten!(level)
482
+ def flatten!(level = undefined)
481
483
  %x{
482
484
  var size = #{self}.length;
483
485
  #{replace flatten level};
@@ -601,7 +603,7 @@ class Array < `Array`
601
603
  self
602
604
  end
603
605
 
604
- def last(count)
606
+ def last(count = undefined)
605
607
  %x{
606
608
  var length = #{self}.length;
607
609
 
@@ -628,7 +630,7 @@ class Array < `Array`
628
630
 
629
631
  alias map! collect!
630
632
 
631
- def pop(count)
633
+ def pop(count = undefined)
632
634
  %x{
633
635
  var length = #{self}.length;
634
636
 
@@ -772,7 +774,7 @@ class Array < `Array`
772
774
  }
773
775
  end
774
776
 
775
- def shift(count)
777
+ def shift(count = undefined)
776
778
  %x{
777
779
  if (#{self}.length === 0) {
778
780
  return nil;
@@ -799,7 +801,7 @@ class Array < `Array`
799
801
 
800
802
  alias slice :[]
801
803
 
802
- def slice!(index, length)
804
+ def slice!(index, length = undefined)
803
805
  %x{
804
806
  if (index < 0) {
805
807
  index += #{self}.length;
@@ -8,7 +8,14 @@ class BasicObject
8
8
 
9
9
  def __send__(symbol, *args, &block)
10
10
  %x{
11
- return #{self}['$' + symbol].apply(#{self}, args);
11
+ var func = #{self}['$' + symbol]
12
+
13
+ if (func) {
14
+ if (block !== nil) { args.push(block); }
15
+ return func.apply(#{self}, args);
16
+ }
17
+
18
+ return #{self}.$method_missing.apply(#{self}, [symbol].concat(args));
12
19
  }
13
20
  end
14
21
 
@@ -141,6 +141,20 @@ class Class
141
141
  }
142
142
  end
143
143
 
144
+ def const_set(name, value)
145
+ raise NameError, "wrong constant name #{name}" unless name =~ /^[A-Z]/
146
+ raise NameError, "wrong constant name #{name}" unless name =~ /^[\w_]+$/
147
+ begin
148
+ name = name.to_str
149
+ rescue
150
+ raise TypeError, 'conversion with #to_str failed'
151
+ end
152
+ %x{
153
+ #{self}._scope[name] = #{value};
154
+ return #{value}
155
+ }
156
+ end
157
+
144
158
  def define_method(name, &block)
145
159
  %x{
146
160
  if (block === nil) {
@@ -224,7 +238,7 @@ class Class
224
238
  `#{self}._name`
225
239
  end
226
240
 
227
- def new()
241
+ def new(*)
228
242
  %x{
229
243
  var args = __slice.call(arguments);
230
244
  var obj = new #{self};
@@ -24,7 +24,7 @@ class Date
24
24
  }
25
25
  end
26
26
 
27
- def initialize(year, month, day)
27
+ def initialize(year = undefined, month = undefined, day = undefined)
28
28
  `#{self}._date = new native_date(year, month - 1, day)`
29
29
  end
30
30
 
@@ -0,0 +1,30 @@
1
+ class Enumerator
2
+ include Enumerable
3
+
4
+ def initialize(obj, method = :each, *args)
5
+ @object = obj
6
+ @method = method
7
+ @args = args
8
+ end
9
+
10
+ def each(&block)
11
+ return enum_for :each unless block_given?
12
+
13
+ @object.__send__(@method, *@args) do |e|
14
+ block.call e
15
+ end
16
+ end
17
+
18
+ def next
19
+ @cache ||= to_a
20
+
21
+ raise StopIteration, 'end of enumeration' if @cache.empty?
22
+
23
+ @cache.shift
24
+ end
25
+
26
+ def rewind
27
+ @cache = nil
28
+ self
29
+ end
30
+ end
@@ -5,6 +5,7 @@ class Exception < `Error`
5
5
  %x{
6
6
  var err = new Error(message);
7
7
  err._klass = #{self};
8
+ err.name = #{self}._name;
8
9
  return err;
9
10
  }
10
11
  end
@@ -31,13 +32,14 @@ class Exception < `Error`
31
32
  alias to_s message
32
33
  end
33
34
 
34
- StandardError = Exception
35
- RuntimeError = Exception
36
- LocalJumpError = Exception
37
- TypeError = Exception
38
- NameError = Exception
39
- NoMethodError = Exception
40
- ArgumentError = Exception
41
- IndexError = Exception
42
- KeyError = Exception
43
- RangeError = Exception
35
+ class StandardError < Exception; end
36
+ class RuntimeError < Exception; end
37
+ class LocalJumpError < Exception; end
38
+ class TypeError < Exception; end
39
+ class NameError < Exception; end
40
+ class NoMethodError < Exception; end
41
+ class ArgumentError < Exception; end
42
+ class IndexError < Exception; end
43
+ class KeyError < Exception; end
44
+ class RangeError < Exception; end
45
+ class StopIteration < Exception; end
@@ -177,7 +177,7 @@ class Hash
177
177
  }
178
178
  end
179
179
 
180
- def default
180
+ def default(val = undefined)
181
181
  @none
182
182
  end
183
183
 
@@ -92,6 +92,10 @@ module Kernel
92
92
  }
93
93
  end
94
94
 
95
+ def enum_for(method = :each, *args)
96
+ Enumerator.new self, method, *args
97
+ end
98
+
95
99
  def equal?(other)
96
100
  `#{self} === other`
97
101
  end
@@ -364,7 +368,7 @@ module Kernel
364
368
  }
365
369
  end
366
370
 
367
- def rand(max)
371
+ def rand(max = undefined)
368
372
  `max == null ? Math.random() : Math.floor(Math.random() * max)`
369
373
  end
370
374
 
@@ -190,6 +190,8 @@ class Numeric < `Number`
190
190
  end
191
191
 
192
192
  def upto(finish, &block)
193
+ return enum_for :upto, finish unless block_given?
194
+
193
195
  %x{
194
196
  for (var i = #{self}; i <= finish; i++) {
195
197
  if (block(i) === __breaker) {
@@ -36,7 +36,7 @@ class Regexp < `RegExp`
36
36
 
37
37
  alias_native :inspect, :toString
38
38
 
39
- def match(pattern)
39
+ def match(pattern, pos = undefined)
40
40
  %x{
41
41
  var result = #{self}.exec(pattern);
42
42
 
@@ -240,6 +240,18 @@
240
240
  }
241
241
  };
242
242
 
243
+ // Const missing dispatcher
244
+ Opal.cm = function(name) {
245
+ throw Opal.NameError.$new('uninitialized constant ' + name);
246
+ };
247
+
248
+ // Arity count error dispatcher
249
+ Opal.ac = function(actual, expected, object, meth) {
250
+ var inspect = (object._isObject ? object._klass._name + '#' : object._name + '.') + meth;
251
+ var msg = '[' + inspect + '] wrong number of arguments(' + actual + ' for ' + expected + ')'
252
+ throw Opal.ArgumentError.$new(msg);
253
+ }
254
+
243
255
  // Initialization
244
256
  // --------------
245
257
 
@@ -90,7 +90,7 @@ class String < `String`
90
90
  }
91
91
  end
92
92
 
93
- def [](index, length)
93
+ def [](index, length = undefined)
94
94
  %x{
95
95
  var size = #{self}.length;
96
96
 
@@ -243,7 +243,7 @@ class String < `String`
243
243
 
244
244
  alias_native :getbyte, :charCodeAt
245
245
 
246
- def gsub(pattern, replace)
246
+ def gsub(pattern, replace = undefined)
247
247
  if pattern.is_a?(String)
248
248
  pattern = /#{Regexp.escape(pattern)}/
249
249
  end
@@ -346,7 +346,7 @@ class String < `String`
346
346
  `#{self}.replace(/^\\s*/, '')`
347
347
  end
348
348
 
349
- def match(pattern, pos, &block)
349
+ def match(pattern, pos = undefined, &block)
350
350
  (pattern.is_a?(Regexp) ? pattern : /#{Regexp.escape(pattern)}/).match(self, pos, &block)
351
351
  end
352
352
 
@@ -507,7 +507,7 @@ class String < `String`
507
507
  %x{
508
508
  var name = '$' + #{self};
509
509
 
510
- return function(arg) { return arg[name](arg); };
510
+ return function(arg) { return arg[name](); };
511
511
  }
512
512
  end
513
513
 
@@ -5,7 +5,7 @@ class Time < `Date`
5
5
  `new Date(seconds * 1000 + frac)`
6
6
  end
7
7
 
8
- def self.new(year, month, day, hour, minute, second, millisecond)
8
+ def self.new(year = undefined, month = undefined, day = undefined, hour = undefined, minute = undefined, second = undefined, millisecond = undefined)
9
9
  %x{
10
10
  switch (arguments.length) {
11
11
  case 1:
@@ -1,6 +1,7 @@
1
1
  require 'opal/parser'
2
2
  require 'opal/processor'
3
3
  require 'opal/environment'
4
+ require 'opal/server'
4
5
  require 'opal/version'
5
6
 
6
7
  # Opal is a ruby to javascript compiler, with a runtime for running
@@ -99,6 +99,7 @@ module Opal
99
99
  @file = options[:file] || '(file)'
100
100
  @method_missing = (options[:method_missing] != false)
101
101
  @optimized_operators = (options[:optimized_operators] != false)
102
+ @arity_check = options[:arity_check]
102
103
 
103
104
  top @grammar.parse(source, @file)
104
105
  end
@@ -875,7 +876,7 @@ module Opal
875
876
 
876
877
  unless work.empty?
877
878
  join = work.join ', '
878
- code += (code.empty? ? join : ".concat([#{work}])")
879
+ code += (code.empty? ? join : ".concat([#{join}])")
879
880
  end
880
881
 
881
882
  code
@@ -1043,6 +1044,7 @@ module Opal
1043
1044
  params = nil
1044
1045
  scope_name = nil
1045
1046
  uses_super = nil
1047
+ uses_splat = nil
1046
1048
 
1047
1049
  # opt args if last arg is sexp
1048
1050
  opt = args.pop if Array === args.last
@@ -1057,8 +1059,9 @@ module Opal
1057
1059
 
1058
1060
  # splat args *splat
1059
1061
  if args.last.to_s.start_with? '*'
1062
+ uses_splat = true
1060
1063
  if args.last == :*
1061
- args.pop
1064
+ #args[-1] = splat
1062
1065
  argc -= 1
1063
1066
  else
1064
1067
  splat = args[-1].to_s[1..-1].to_sym
@@ -1069,6 +1072,10 @@ module Opal
1069
1072
 
1070
1073
  args << block_name if block_name # have to re-add incase there was a splat arg
1071
1074
 
1075
+ if @arity_check
1076
+ arity_code = arity_check(args, opt, uses_splat, block_name, mid) + "\n#{INDENT}"
1077
+ end
1078
+
1072
1079
  indent do
1073
1080
  in_scope(:def) do
1074
1081
  @scope.mid = mid
@@ -1137,7 +1144,7 @@ module Opal
1137
1144
 
1138
1145
  uses_super = @scope.uses_super
1139
1146
 
1140
- code = "#@indent#{@scope.to_vars}" + code
1147
+ code = "#{arity_code}#@indent#{@scope.to_vars}" + code
1141
1148
  end
1142
1149
  end
1143
1150
 
@@ -1167,17 +1174,22 @@ module Opal
1167
1174
 
1168
1175
  ##
1169
1176
  # Returns code used in debug mode to check arity of method call
1170
- def arity_check(args, opt, splat)
1177
+ def arity_check(args, opt, splat, block_name, mid)
1178
+ meth = mid.to_s.inspect
1179
+
1171
1180
  arity = args.size - 1
1172
1181
  arity -= (opt.size - 1) if opt
1173
1182
  arity -= 1 if splat
1183
+ arity -= 1 if block_name
1174
1184
  arity = -arity - 1 if opt or splat
1175
1185
 
1176
- aritycode = "var $arity = arguments.length; if ($arity !== 0) { $arity -= 1; }"
1186
+ # $arity will point to our received arguments count
1187
+ aritycode = "var $arity = arguments.length;"
1188
+
1177
1189
  if arity < 0 # splat or opt args
1178
- aritycode + "if ($arity < #{-(arity + 1)}) { opal.arg_error($arity, #{arity}); }"
1190
+ aritycode + "if ($arity < #{-(arity + 1)}) { __opal.ac($arity, #{arity}, this, #{meth}); }"
1179
1191
  else
1180
- aritycode + "if ($arity !== #{arity}) { opal.arg_error($arity, #{arity}); }"
1192
+ aritycode + "if ($arity !== #{arity} && (typeof(arguments[$arity - 1]) !== 'function' || ($arity - 1) !== #{arity})) { __opal.ac($arity, #{arity}, this, #{meth}); }"
1181
1193
  end
1182
1194
  end
1183
1195
 
@@ -1186,6 +1198,7 @@ module Opal
1186
1198
 
1187
1199
  until exp.empty?
1188
1200
  a = exp.shift.to_sym
1201
+ next if a.to_s == '*'
1189
1202
  a = "#{a}$".to_sym if RESERVED.include? a.to_s
1190
1203
  @scope.add_arg a
1191
1204
  args << a
@@ -1473,7 +1486,11 @@ module Opal
1473
1486
 
1474
1487
  # s(:const, :const)
1475
1488
  def process_const(sexp, level)
1476
- "__scope.#{sexp.shift}"
1489
+ cname = sexp.shift.to_s
1490
+
1491
+ with_temp do |t|
1492
+ "((#{t} = __scope.#{cname}) == null ? __opal.cm(#{cname.inspect}) : #{t})"
1493
+ end
1477
1494
  end
1478
1495
 
1479
1496
  # s(:cdecl, :const, rhs)
@@ -1811,12 +1828,19 @@ module Opal
1811
1828
  # s(:colon2, base, :NAME)
1812
1829
  def process_colon2(sexp, level)
1813
1830
  base = sexp[0]
1814
- name = sexp[1]
1815
- "(%s)._scope.%s" % [process(base, :expr), name.to_s]
1831
+ cname = sexp[1].to_s
1832
+
1833
+ with_temp do |t|
1834
+ base = process base, :expr
1835
+ "((#{t} = (#{base})._scope.#{cname}) == null ? __opal.cm(#{cname.inspect}) : #{t})"
1836
+ end
1816
1837
  end
1817
1838
 
1818
1839
  def process_colon3(exp, level)
1819
- "__opal.Object._scope.#{exp.shift.to_s}"
1840
+ with_temp do |t|
1841
+ cname = exp.shift.to_s
1842
+ "((#{t} = __opal.Object._scope.#{cname}) == null ? __opal.cm(#{cname.inspect}) : #{t})"
1843
+ end
1820
1844
  end
1821
1845
 
1822
1846
  # super a, b, c
@@ -12,22 +12,24 @@ module Opal
12
12
  class << self
13
13
  attr_accessor :method_missing_enabled
14
14
  attr_accessor :optimized_operators_enabled
15
+ attr_accessor :arity_check_enabled
15
16
  end
16
17
 
17
18
  self.method_missing_enabled = true
18
19
  self.optimized_operators_enabled = true
20
+ self.arity_check_enabled = false
19
21
 
20
22
  def initialize_engine
21
23
  require_template_library 'opal'
22
24
  end
23
25
 
24
26
  def prepare
25
- # ...
26
27
  end
27
28
 
28
29
  def evaluate(context, locals, &block)
29
- options = { :method_missing => self.class.method_missing_enabled,
30
- :optimized_operators => self.class.optimized_operators_enabled }
30
+ options = { :method_missing => self.class.method_missing_enabled,
31
+ :optimized_operators => self.class.optimized_operators_enabled,
32
+ :arity_check => self.class.arity_check_enabled }
31
33
 
32
34
  parser = Opal::Parser.new
33
35
  result = parser.parse data, options
@@ -0,0 +1,92 @@
1
+ require 'opal'
2
+ require 'erb'
3
+
4
+ module Opal
5
+ class Server
6
+
7
+ attr_accessor :debug, :index_path, :main, :public_dir, :sprockets
8
+
9
+ def initialize(debug = true)
10
+ @sprockets = Opal::Environment.new
11
+ @public_dir = '.'
12
+ @debug = debug
13
+
14
+ yield self if block_given?
15
+ create_app
16
+ end
17
+
18
+ def append_path(path)
19
+ @sprockets.append_path path
20
+ end
21
+
22
+ def create_app
23
+ server, sprockets = self, @sprockets
24
+
25
+ @app = Rack::Builder.app do
26
+ map('/assets') { run sprockets }
27
+ use Index, server
28
+ run Rack::Directory.new(server.public_dir)
29
+ end
30
+ end
31
+
32
+ def call(env)
33
+ @app.call env
34
+ end
35
+
36
+ class Index
37
+
38
+ def initialize(app, server)
39
+ @app = app
40
+ @server = server
41
+ @index_path = server.index_path
42
+ end
43
+
44
+ def call(env)
45
+ if %w[/ /index.html].include? env['PATH_INFO']
46
+ [200, { 'Content-Type' => 'text/html' }, [html]]
47
+ else
48
+ @app.call env
49
+ end
50
+ end
51
+
52
+ def html
53
+ source = if @index_path
54
+ raise "index does not exist: #{@index_path}" unless File.exist?(@index_path)
55
+ File.read @index_path
56
+ else
57
+ SOURCE
58
+ end
59
+
60
+ ERB.new(source).result binding
61
+ end
62
+
63
+ def javascript_include_tag(source)
64
+ if @server.debug
65
+ assets = @server.sprockets[source].to_a
66
+
67
+ raise "Cannot find asset: #{source}" if assets.empty?
68
+
69
+ scripts = assets.map do |a|
70
+ %Q{<script src="/assets/#{ a.logical_path }?body=1"></script>}
71
+ end
72
+
73
+ scripts.join "\n"
74
+ else
75
+ "<script src=\"/assets/#{source}.js\"></script>"
76
+ end
77
+ end
78
+
79
+ SOURCE = <<-HTML
80
+ <!DOCTYPE html>
81
+ <html>
82
+ <head>
83
+ <title>Opal Server</title>
84
+ </head>
85
+ <body>
86
+ <%= javascript_include_tag @server.main %>
87
+ </body>
88
+ </html>
89
+ HTML
90
+ end
91
+ end
92
+ end
@@ -1,3 +1,3 @@
1
1
  module Opal
2
- VERSION = '0.3.39'
2
+ VERSION = '0.3.40'
3
3
  end
@@ -5,4 +5,8 @@ describe "Array#each" do
5
5
  x.each { |item| a << item }.should equal(x)
6
6
  a.should == [1, 2, 3]
7
7
  end
8
- end
8
+
9
+ it "returns an Enumerator if no block given" do
10
+ [1, 2].each.should be_kind_of(Enumerator)
11
+ end
12
+ end
@@ -0,0 +1,11 @@
1
+ describe "Enumerator#each" do
2
+ it "yield each element of self to the given block" do
3
+ acc = []
4
+ enumerator_class.new([1, 2, 3]).each {|e| acc << e }
5
+ acc.should == [1,2,3]
6
+ end
7
+
8
+ it "returns an enumerator if no block is given" do
9
+ enumerator_class.new([1]).each.should be_kind_of(enumerator_class)
10
+ end
11
+ end
@@ -0,0 +1,17 @@
1
+ require "spec_helper"
2
+
3
+ describe "Enumerator#new" do
4
+ it "creates a new custom enumerator with the given object, iterator and arguments" do
5
+ enum = enumerator_class.new(1, :upto, 3)
6
+ enum.should be_kind_of(Enumerator)
7
+ end
8
+
9
+ it "creates a new custom enumerator that responds to #each" do
10
+ enum = enumerator_class.new(1, :upto, 3)
11
+ enum.respond_to?(:each).should == true
12
+ end
13
+
14
+ it "creates a new custom enumerator that runs correctly" do
15
+ enumerator_class.new(1, :upto, 3).map{|x|x}.should == [1,2,3]
16
+ end
17
+ end
@@ -0,0 +1,25 @@
1
+ describe "Enumerator#next" do
2
+ before :each do
3
+ @enum = enumerator_class.new(1, :upto, 3)
4
+ end
5
+
6
+ it "returns the next element of the enumeration" do
7
+ @enum.next.should == 1
8
+ @enum.next.should == 2
9
+ @enum.next.should == 3
10
+ end
11
+
12
+ it "raises a StopIteration exception at the end of the stream" do
13
+ 3.times { @enum.next }
14
+ lambda { @enum.next }.should raise_error(StopIteration)
15
+ end
16
+
17
+ it "cannot be called again until the enumerator is rewound" do
18
+ 3.times { @enum.next }
19
+ lambda { @enum.next }.should raise_error(StopIteration)
20
+ lambda { @enum.next }.should raise_error(StopIteration)
21
+ lambda { @enum.next }.should raise_error(StopIteration)
22
+ @enum.rewind
23
+ @enum.next.should == 1
24
+ end
25
+ end
@@ -0,0 +1,28 @@
1
+ describe "Enumerator#rewind" do
2
+ before(:each) do
3
+ @enum = enumerator_class.new(1, :upto, 3)
4
+ end
5
+
6
+ it "resets the enumerator to its initial state" do
7
+ @enum.next.should == 1
8
+ @enum.next.should == 2
9
+ @enum.rewind
10
+ @enum.next.should == 1
11
+ end
12
+
13
+ it "returns self" do
14
+ @enum.rewind.should == @enum
15
+ end
16
+
17
+ it "has no effect on a new enumerator" do
18
+ @enum.rewind
19
+ @enum.next.should == 1
20
+ end
21
+
22
+ it "has no effect if called multiple, consecutive times" do
23
+ @enum.next.should == 1
24
+ @enum.rewind
25
+ @enum.rewind
26
+ @enum.next.should == 1
27
+ end
28
+ end
@@ -0,0 +1,65 @@
1
+ require File.expand_path('../../../spec_helper', __FILE__)
2
+ require File.expand_path('../../../fixtures/constants', __FILE__)
3
+
4
+
5
+ module ConstantSpecs
6
+ end
7
+
8
+ describe "Module#const_set" do
9
+ it "sets the constant specified by a String or Symbol to the given value" do
10
+ ConstantSpecs.const_set :CS_CONST401, :const401
11
+ ConstantSpecs::CS_CONST401.should == :const401
12
+
13
+ ConstantSpecs.const_set "CS_CONST402", :const402
14
+ ConstantSpecs.const_get(:CS_CONST402).should == :const402
15
+ end
16
+
17
+ it "returns the value set" do
18
+ ConstantSpecs.const_set(:CS_CONST403, :const403).should == :const403
19
+ end
20
+
21
+ # PENDING: needs proper parser implementation
22
+ #
23
+ # it "sets the name of an anonymous module" do
24
+ # m = Module.new
25
+ # ConstantSpecs.const_set(:CS_CONST1000, m)
26
+ # m.name.should == "ConstantSpecs::CS_CONST1000"
27
+ # end
28
+
29
+ it "raises a NameError if the name does not start with a capital letter" do
30
+ lambda { ConstantSpecs.const_set "name", 1 }.should raise_error(NameError)
31
+ end
32
+
33
+ it "raises a NameError if the name starts with a non-alphabetic character" do
34
+ lambda { ConstantSpecs.const_set "__CONSTX__", 1 }.should raise_error(NameError)
35
+ lambda { ConstantSpecs.const_set "@Name", 1 }.should raise_error(NameError)
36
+ lambda { ConstantSpecs.const_set "!Name", 1 }.should raise_error(NameError)
37
+ lambda { ConstantSpecs.const_set "::Name", 1 }.should raise_error(NameError)
38
+ end
39
+
40
+ it "raises a NameError if the name contains non-alphabetic characters except '_'" do
41
+ ConstantSpecs.const_set("CS_CONST404", :const404).should == :const404
42
+ lambda { ConstantSpecs.const_set "Name=", 1 }.should raise_error(NameError)
43
+ lambda { ConstantSpecs.const_set "Name?", 1 }.should raise_error(NameError)
44
+ end
45
+
46
+ # PENDING: should_receive isn't available on opal-spec
47
+ #
48
+ # it "calls #to_str to convert the given name to a String" do
49
+ #
50
+ # name = mock("CS_CONST405")
51
+ # name.should_receive(:to_str).and_return("CS_CONST405")
52
+ # ConstantSpecs.const_set(name, :const405).should == :const405
53
+ # ConstantSpecs::CS_CONST405.should == :const405
54
+ # end
55
+
56
+ # PENDING: should_receive isn't available on opal-spec
57
+ #
58
+ # it "raises a TypeError if conversion to a String by calling #to_str fails" do
59
+ # name = mock('123')
60
+ # lambda { ConstantSpecs.const_set name, 1 }.should raise_error(TypeError)
61
+ #
62
+ # name.should_receive(:to_str).and_return(123)
63
+ # lambda { ConstantSpecs.const_set name, 1 }.should raise_error(TypeError)
64
+ # end
65
+ end
@@ -0,0 +1,28 @@
1
+ require "spec_helper"
2
+
3
+ class BasicObjectSendSpec
4
+ def foo
5
+ :bar
6
+ end
7
+
8
+ def method_missing(symbol, *args, &block)
9
+ "called_#{symbol}"
10
+ end
11
+
12
+ class Subclass < BasicObjectSendSpec
13
+ def method_missing(symbol, *args, &block)
14
+ args
15
+ end
16
+ end
17
+ end
18
+
19
+ describe "BasicObject#__send__" do
20
+ it "should call method_missing for undefined method" do
21
+ BasicObjectSendSpec.new.__send__(:foo).should eq(:bar)
22
+ BasicObjectSendSpec.new.__send__(:pow).should eq('called_pow')
23
+ end
24
+
25
+ it "should pass on arguments to method_missing" do
26
+ BasicObjectSendSpec::Subclass.new.__send__(:blah, 1, 2, 3).should eq([1, 2, 3])
27
+ end
28
+ end
@@ -0,0 +1,13 @@
1
+ describe "Missing constants" do
2
+ it "should raise a NameError when trying to access an undefined constant" do
3
+ lambda { ThisConstantDoesNotExist }.should raise_error(NameError)
4
+ end
5
+
6
+ it "raises an error for missing constants on base constant scope" do
7
+ lambda { Object::SomeRandomObjectName }.should raise_error(NameError)
8
+ end
9
+
10
+ it "raises an error for missing constants on root constant scope" do
11
+ lambda { ::YetAnotherMissingConstant }.should raise_error(NameError)
12
+ end
13
+ end
@@ -4,6 +4,7 @@ require 'opal-spec'
4
4
 
5
5
  # stdlib
6
6
  require 'opal/date'
7
+ require 'opal/enumerator'
7
8
 
8
9
  module Kernel
9
10
  def opal_eval(str)
@@ -24,4 +25,8 @@ module Kernel
24
25
  def ruby_version_is(version, &block)
25
26
  block.call
26
27
  end
28
+
29
+ def enumerator_class
30
+ Enumerator
31
+ end
27
32
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: opal
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.39
4
+ version: 0.3.40
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-02-20 00:00:00.000000000 Z
12
+ date: 2013-02-23 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: sprockets
@@ -53,6 +53,7 @@ files:
53
53
  - lib/assets/javascripts/opal/comparable.rb
54
54
  - lib/assets/javascripts/opal/date.rb
55
55
  - lib/assets/javascripts/opal/enumerable.rb
56
+ - lib/assets/javascripts/opal/enumerator.rb
56
57
  - lib/assets/javascripts/opal/error.rb
57
58
  - lib/assets/javascripts/opal/hash.rb
58
59
  - lib/assets/javascripts/opal/json.rb
@@ -78,6 +79,7 @@ files:
78
79
  - lib/opal/parser.rb
79
80
  - lib/opal/processor.rb
80
81
  - lib/opal/scope.rb
82
+ - lib/opal/server.rb
81
83
  - lib/opal/version.rb
82
84
  - opal.gemspec
83
85
  - spec/core/array/allocate_spec.rb
@@ -177,6 +179,10 @@ files:
177
179
  - spec/core/enumerable/select_spec.rb
178
180
  - spec/core/enumerable/take_spec.rb
179
181
  - spec/core/enumerable/to_a_spec.rb
182
+ - spec/core/enumerator/each_spec.rb
183
+ - spec/core/enumerator/new_spec.rb
184
+ - spec/core/enumerator/next_spec.rb
185
+ - spec/core/enumerator/rewind_spec.rb
180
186
  - spec/core/hash/allocate_spec.rb
181
187
  - spec/core/hash/assoc_spec.rb
182
188
  - spec/core/hash/clear_spec.rb
@@ -256,6 +262,7 @@ files:
256
262
  - spec/core/module/ancestors_spec.rb
257
263
  - spec/core/module/append_features_spec.rb
258
264
  - spec/core/module/const_get_spec.rb
265
+ - spec/core/module/const_set_spec.rb
259
266
  - spec/core/module/undef_method_spec.rb
260
267
  - spec/core/nil/and_spec.rb
261
268
  - spec/core/nil/inspect_spec.rb
@@ -372,8 +379,10 @@ files:
372
379
  - spec/core/time/now_spec.rb
373
380
  - spec/core/time/saturday_spec.rb
374
381
  - spec/core_ext/array/to_json_spec.rb
382
+ - spec/core_ext/basic_object/send_spec.rb
375
383
  - spec/core_ext/class/_inherited_spec.rb
376
384
  - spec/core_ext/class/singleton_methods_spec.rb
385
+ - spec/core_ext/constants_spec.rb
377
386
  - spec/core_ext/method_missing_spec.rb
378
387
  - spec/core_ext/native/fixtures/classes.rb
379
388
  - spec/core_ext/native/initialize_spec.rb
@@ -582,6 +591,10 @@ test_files:
582
591
  - spec/core/enumerable/select_spec.rb
583
592
  - spec/core/enumerable/take_spec.rb
584
593
  - spec/core/enumerable/to_a_spec.rb
594
+ - spec/core/enumerator/each_spec.rb
595
+ - spec/core/enumerator/new_spec.rb
596
+ - spec/core/enumerator/next_spec.rb
597
+ - spec/core/enumerator/rewind_spec.rb
585
598
  - spec/core/hash/allocate_spec.rb
586
599
  - spec/core/hash/assoc_spec.rb
587
600
  - spec/core/hash/clear_spec.rb
@@ -661,6 +674,7 @@ test_files:
661
674
  - spec/core/module/ancestors_spec.rb
662
675
  - spec/core/module/append_features_spec.rb
663
676
  - spec/core/module/const_get_spec.rb
677
+ - spec/core/module/const_set_spec.rb
664
678
  - spec/core/module/undef_method_spec.rb
665
679
  - spec/core/nil/and_spec.rb
666
680
  - spec/core/nil/inspect_spec.rb
@@ -777,8 +791,10 @@ test_files:
777
791
  - spec/core/time/now_spec.rb
778
792
  - spec/core/time/saturday_spec.rb
779
793
  - spec/core_ext/array/to_json_spec.rb
794
+ - spec/core_ext/basic_object/send_spec.rb
780
795
  - spec/core_ext/class/_inherited_spec.rb
781
796
  - spec/core_ext/class/singleton_methods_spec.rb
797
+ - spec/core_ext/constants_spec.rb
782
798
  - spec/core_ext/method_missing_spec.rb
783
799
  - spec/core_ext/native/fixtures/classes.rb
784
800
  - spec/core_ext/native/initialize_spec.rb