opal 0.3.39 → 0.3.40

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