opal 0.3.37 → 0.3.38

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. data/CHANGELOG.md +11 -0
  2. data/Gemfile +0 -8
  3. data/README.md +7 -6
  4. data/bin/opal +18 -10
  5. data/config.ru +8 -21
  6. data/lib/assets/javascripts/opal-parser.js.erb +3 -60
  7. data/lib/assets/javascripts/opal/array.rb +87 -43
  8. data/lib/assets/javascripts/opal/basic_object.rb +4 -0
  9. data/lib/assets/javascripts/opal/boolean.rb +5 -3
  10. data/lib/assets/javascripts/opal/class.rb +19 -4
  11. data/lib/assets/javascripts/opal/comparable.rb +1 -1
  12. data/lib/assets/javascripts/opal/enumerable.rb +32 -0
  13. data/lib/assets/javascripts/opal/error.rb +1 -1
  14. data/lib/assets/javascripts/opal/hash.rb +166 -103
  15. data/lib/assets/javascripts/opal/json.rb +3 -2
  16. data/lib/assets/javascripts/opal/kernel.rb +9 -1
  17. data/lib/assets/javascripts/opal/native.rb +29 -0
  18. data/lib/assets/javascripts/opal/nil_class.rb +9 -1
  19. data/lib/assets/javascripts/opal/numeric.rb +6 -4
  20. data/lib/assets/javascripts/opal/parser.js +57 -0
  21. data/lib/assets/javascripts/opal/proc.rb +5 -5
  22. data/lib/assets/javascripts/opal/regexp.rb +1 -1
  23. data/lib/assets/javascripts/opal/runtime.js +13 -0
  24. data/lib/assets/javascripts/opal/string.rb +14 -3
  25. data/lib/assets/javascripts/opal/time.rb +1 -1
  26. data/lib/opal.rb +1 -1
  27. data/lib/opal/parser.rb +39 -13
  28. data/lib/opal/processor.rb +13 -2
  29. data/lib/opal/version.rb +1 -1
  30. data/opal.gemspec +3 -0
  31. data/spec/core/array/fill_spec.rb +26 -0
  32. data/spec/core/array/try_convert_spec.rb +15 -0
  33. data/spec/core/enumerable/each_slice_spec.rb +24 -0
  34. data/spec/core/enumerable/group_by_spec.rb +16 -0
  35. data/spec/core/module/const_get_spec.rb +34 -0
  36. data/spec/core/module/undef_method_spec.rb +67 -0
  37. data/spec/core/nil/to_h_spec.rb +10 -0
  38. data/spec/core/proc/element_reference_spec.rb +21 -0
  39. data/spec/{core → core_ext}/array/to_json_spec.rb +0 -0
  40. data/spec/core_ext/method_missing_spec.rb +43 -0
  41. data/spec/core_ext/native/fixtures/classes.rb +5 -0
  42. data/spec/core_ext/native/initialize_spec.rb +8 -0
  43. data/spec/core_ext/native/method_missing_spec.rb +7 -0
  44. data/spec/core_ext/native/to_native_spec.rb +7 -0
  45. data/spec/grammar/parser_spec.rb +1 -1
  46. data/spec/language/super_spec.rb +20 -0
  47. data/spec/language/variables_spec.rb +69 -0
  48. data/spec/spec_helper.rb +9 -5
  49. metadata +66 -8
  50. data/lib/assets/javascripts/opal/core.rb +0 -36
  51. data/spec/autorun.rb +0 -3
@@ -9,6 +9,14 @@ module Opal
9
9
  true
10
10
  end
11
11
 
12
+ class << self
13
+ attr_accessor :method_missing_enabled
14
+ attr_accessor :optimized_operators_enabled
15
+ end
16
+
17
+ self.method_missing_enabled = true
18
+ self.optimized_operators_enabled = true
19
+
12
20
  def initialize_engine
13
21
  require_template_library 'opal'
14
22
  end
@@ -18,8 +26,11 @@ module Opal
18
26
  end
19
27
 
20
28
  def evaluate(context, locals, &block)
21
- parser = Opal::Parser.new
22
- result = parser.parse data
29
+ options = { :method_missing => self.class.method_missing_enabled,
30
+ :optimized_operators => self.class.optimized_operators_enabled }
31
+
32
+ parser = Opal::Parser.new
33
+ result = parser.parse data, options
23
34
 
24
35
  parser.requires.each { |r| context.require_asset r }
25
36
  result
data/lib/opal/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Opal
2
- VERSION = '0.3.37'
2
+ VERSION = '0.3.38'
3
3
  end
data/opal.gemspec CHANGED
@@ -16,4 +16,7 @@ Gem::Specification.new do |s|
16
16
  s.require_paths = ['lib']
17
17
 
18
18
  s.add_runtime_dependency 'sprockets'
19
+
20
+ s.add_development_dependency 'opal-spec', '~> 0.2.10'
21
+ s.add_development_dependency 'racc'
19
22
  end
@@ -0,0 +1,26 @@
1
+ require "spec_helper"
2
+
3
+ describe "Array#fill" do
4
+ it "returns self" do
5
+ ary = [1, 2, 3]
6
+ ary.fill(:a).should equal(ary)
7
+ end
8
+
9
+ it "is destructive" do
10
+ ary = [1, 2, 3]
11
+ ary.fill(:a)
12
+ ary.should == [:a, :a, :a]
13
+ end
14
+
15
+ it "replaces all elements in the array with the filler if not given an index nor a length" do
16
+ ary = ['a', 'b', 'c', 'duh']
17
+ ary.fill(8).should == [8, 8, 8, 8]
18
+
19
+ str = "x"
20
+ ary.fill(str).should == [str, str, str, str]
21
+ end
22
+
23
+ it "replaces all elements with the value of block (index given to block)" do
24
+ [nil, nil, nil, nil].fill { |i| i * 2 }.should == [0, 2, 4, 6]
25
+ end
26
+ end
@@ -0,0 +1,15 @@
1
+ require File.expand_path('../../../spec_helper', __FILE__)
2
+ require File.expand_path('../fixtures/classes', __FILE__)
3
+
4
+ ruby_version_is "1.9" do
5
+ describe "Array.try_convert" do
6
+ it "returns the argument if it's a Array" do
7
+ x = Array.new
8
+ Array.try_convert(x).should equal(x)
9
+ end
10
+
11
+ it "returns nil when the argument does not respond to #to_ary" do
12
+ Array.try_convert(Object.new).should be_nil
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,24 @@
1
+ require "spec_helper"
2
+
3
+ describe "Enumerable#each_slice" do
4
+ before :each do
5
+ @enum = EnumerableSpecs::Numerous.new(7,6,5,4,3,2,1)
6
+ @sliced = [[7,6,5],[4,3,2],[1]]
7
+ end
8
+
9
+ it "passes element groups to the block" do
10
+ acc = []
11
+ @enum.each_slice(3) { |g| acc << g }.should be_nil
12
+ acc.should == @sliced
13
+ end
14
+
15
+ it "works when n is >= full length" do
16
+ full = @enum.to_a
17
+ acc = []
18
+ @enum.each_slice(full.length) { |g| acc << g }
19
+ acc.should == [full]
20
+ acc = []
21
+ @enum.each_slice(full.length + 1) { |g| acc << g }
22
+ acc.should == [full]
23
+ end
24
+ end
@@ -0,0 +1,16 @@
1
+ describe "Enumerable#group_by" do
2
+ it "returns a hash with values grouped according to the block" do
3
+ grouped = [:foo, :bar, :baz].group_by { |word| word[0, 1].to_sym }
4
+ grouped.should == { :f => [:foo], :b => [:bar, :baz] }
5
+ end
6
+
7
+ it "returns an empty hash for empty enumerables" do
8
+ [].group_by { |x| x }.should == {}
9
+ end
10
+
11
+ it "allows nil as a valid key" do
12
+ grouped = [[nil, :foo], [nil, :baz], [42, 100]].group_by { |arr| arr.first }
13
+ grouped[nil].should == [[nil, :foo], [nil, :baz]]
14
+ grouped[42].should == [[42, 100]]
15
+ end
16
+ end
@@ -0,0 +1,34 @@
1
+ require File.expand_path('../../../spec_helper', __FILE__)
2
+ require File.expand_path('../../../fixtures/constants', __FILE__)
3
+
4
+ CS_CONST1 = :const1
5
+
6
+ module ConstGetSpecs
7
+ FOO = 100
8
+
9
+ module Bar
10
+ BAR = 200
11
+
12
+ module Baz
13
+ BAZ = 300
14
+ end
15
+ end
16
+ end
17
+
18
+ describe "Module#const_get" do
19
+ it "accepts a String or Symbol name" do
20
+ Object.const_get(:CS_CONST1).should == :const1
21
+ Object.const_get("CS_CONST1").should == :const1
22
+ end
23
+
24
+ it "raises a NameError if no constant is defined in the search path" do
25
+ lambda { Object.const_get :CS_CONSTX_BAD }.should raise_error(NameError)
26
+ end
27
+
28
+ it "searches parent scopes of classes and modules" do
29
+ ConstGetSpecs::Bar::Baz.const_get(:BAZ).should eq(300)
30
+ ConstGetSpecs::Bar::Baz.const_get(:BAR).should eq(200)
31
+ ConstGetSpecs::Bar::Baz.const_get(:FOO).should eq(100)
32
+ ConstGetSpecs::Bar::Baz.const_get(:Bar).should eq(ConstGetSpecs::Bar)
33
+ end
34
+ end
@@ -0,0 +1,67 @@
1
+ require File.expand_path('../../../spec_helper', __FILE__)
2
+ require File.expand_path('../fixtures/classes', __FILE__)
3
+
4
+ module ModuleSpecs
5
+ class NoInheritance
6
+ def method_to_undef() 1 end
7
+ def another_method_to_undef() 1 end
8
+ end
9
+
10
+ class Parent
11
+ def method_to_undef() 1 end
12
+ def another_method_to_undef() 1 end
13
+ end
14
+
15
+ class Child < Parent
16
+ end
17
+
18
+ class Ancestor
19
+ def method_to_undef() 1 end
20
+ def another_method_to_undef() 1 end
21
+ end
22
+
23
+ class Descendant < Ancestor
24
+ end
25
+ end
26
+
27
+ describe "Module#undef_method with symbol" do
28
+ it "removes a method defined in a class" do
29
+ x = ModuleSpecs::NoInheritance.new
30
+
31
+ x.method_to_undef.should == 1
32
+
33
+ ModuleSpecs::NoInheritance.send :undef_method, :method_to_undef
34
+
35
+ lambda { x.method_to_undef }.should raise_error(NoMethodError)
36
+ end
37
+
38
+ it "removes a method defined in a super class" do
39
+ child = ModuleSpecs::Child.new
40
+ child.method_to_undef.should == 1
41
+
42
+ ModuleSpecs::Child.send :undef_method, :method_to_undef
43
+
44
+ lambda { child.method_to_undef }.should raise_error(NoMethodError)
45
+ end
46
+ end
47
+
48
+ describe "Module#undef_method with string" do
49
+ it "removes a method defined in a class" do
50
+ x = ModuleSpecs::NoInheritance.new
51
+
52
+ x.another_method_to_undef.should == 1
53
+
54
+ ModuleSpecs::NoInheritance.send :undef_method, 'another_method_to_undef'
55
+
56
+ lambda { x.another_method_to_undef }.should raise_error(NoMethodError)
57
+ end
58
+
59
+ it "removes a method defined in a super class" do
60
+ child = ModuleSpecs::Child.new
61
+ child.another_method_to_undef.should == 1
62
+
63
+ ModuleSpecs::Child.send :undef_method, 'another_method_to_undef'
64
+
65
+ lambda { child.another_method_to_undef }.should raise_error(NoMethodError)
66
+ end
67
+ end
@@ -0,0 +1,10 @@
1
+ require File.expand_path('../../../spec_helper', __FILE__)
2
+
3
+ ruby_version_is "2.0" do
4
+ describe "NilClass#to_h" do
5
+ it "returns an empty hash" do
6
+ nil.to_h.should == {}
7
+ nil.to_h.default.should == nil
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,21 @@
1
+ describe "Proc#[]" do
2
+ it "invokes self" do
3
+ Proc.new { "test!" }[].should == "test!"
4
+ lambda { "test!" }[].should == "test!"
5
+ proc { "test!" }[].should == "test!"
6
+ end
7
+
8
+ it "sets self's parameters to the given values" do
9
+ Proc.new { |a, b| a + b }[1, 2].should == 3
10
+ Proc.new { |*args| args }[1, 2, 3, 4].should == [1, 2, 3, 4]
11
+ Proc.new { |_, *args| args }[1, 2, 3].should == [2, 3]
12
+
13
+ lambda { |a, b| a + b }[1, 2].should == 3
14
+ lambda { |*args| args }[1, 2, 3, 4].should == [1, 2, 3, 4]
15
+ lambda { |_, *args| args }[1, 2, 3].should == [2, 3]
16
+
17
+ proc { |a, b| a + b }[1, 2].should == 3
18
+ proc { |*args| args }[1, 2, 3, 4].should == [1, 2, 3, 4]
19
+ proc { |_, *args| args }[1, 2, 3].should == [2, 3]
20
+ end
21
+ end
File without changes
@@ -0,0 +1,43 @@
1
+ require "spec_helper"
2
+
3
+ module MethodMissingSpecs
4
+ class A
5
+ def method_missing(mid, *args)
6
+ [mid, args]
7
+ end
8
+ end
9
+
10
+ class B
11
+ def method_missing(mid, *args, &block)
12
+ [mid, block]
13
+ end
14
+ end
15
+ end
16
+
17
+ describe "method_missing" do
18
+ before do
19
+ @obj = MethodMissingSpecs::A.new
20
+ end
21
+
22
+ it "should pass the missing method name as first argument" do
23
+ @obj.foo.should eq([:foo, []])
24
+ end
25
+
26
+ it "should correctly pass arguments to method_missing" do
27
+ @obj.bar(1, 2, 3).should eq([:bar, [1, 2, 3]])
28
+ end
29
+
30
+ it "should pass blocks to method_missing" do
31
+ obj = MethodMissingSpecs::B.new
32
+ proc = proc { 1 }
33
+ obj.baz(1, 2, &proc).should eq([:baz, proc])
34
+ end
35
+ end
36
+
37
+ describe "BasicObject#method_missing" do
38
+ it "raises an error for the missing method" do
39
+ lambda {
40
+ BasicObject.new.foo_bar_baz
41
+ }.should raise_error(Exception)
42
+ end
43
+ end
@@ -0,0 +1,5 @@
1
+ require "opal/native"
2
+
3
+ class NativeSpecs
4
+ include Native
5
+ end
@@ -0,0 +1,8 @@
1
+ require "spec_helper"
2
+
3
+ describe "Native#initialize" do
4
+ it "raises an error when passed null or undefined" do
5
+ lambda { NativeSpecs.new(`null`) }.should raise_error(Exception)
6
+ lambda { NativeSpecs.new(`undefined`) }.should raise_error(Exception)
7
+ end
8
+ end
@@ -0,0 +1,7 @@
1
+ require "spec_helper"
2
+
3
+ describe "Native#method_missing" do
4
+ it "forwards methods to wrapped object as native function calls" do
5
+ NativeSpecs.new("adam").toUpperCase.should eq("ADAM")
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ require "spec_helper"
2
+
3
+ describe "Native#to_native" do
4
+ it "returns the wrapped object" do
5
+ NativeSpecs.new(:foo).to_native.should eq(:foo)
6
+ end
7
+ end
@@ -22,7 +22,7 @@ describe "Opal::Parser" do
22
22
  it "should parse constant lookups" do
23
23
  opal_eval("Object").should == Object
24
24
  opal_eval("Array").should == Array
25
- opal_eval("OpalSpec::ExampleGroup").should == OpalSpec::ExampleGroup
25
+ opal_eval("Spec::ExampleGroup").should == Spec::ExampleGroup
26
26
  end
27
27
 
28
28
  it "should parse class and module definitions" do
@@ -43,9 +43,29 @@ describe "The super keyword" do
43
43
  it "calls the superclass when initial method is define_method'd" do
44
44
  Super::S7.new.here.should == :good
45
45
  end
46
+
47
+ describe "with no arguments or parens" do
48
+ it "should pass all given arguments in current method to super" do
49
+ Super::NoArgs::B.new.foo(1, 4, 9).should eq([1, 4, 9, 42])
50
+ end
51
+ end
46
52
  end
47
53
 
48
54
  module Super
55
+ module NoArgs
56
+ class A
57
+ def foo(a, b, c)
58
+ [a, b, c]
59
+ end
60
+ end
61
+
62
+ class B < A
63
+ def foo(a, b, c)
64
+ super << 42
65
+ end
66
+ end
67
+ end
68
+
49
69
  module S1
50
70
  class A
51
71
  def foo(a)
@@ -23,6 +23,75 @@ describe "Basic assignment" do
23
23
  a = *[[]]; a.should == [[]]
24
24
  a = *[1,2]; a.should == [1,2]
25
25
  end
26
+
27
+ it "sets unavailable values to nil" do
28
+ ary = []
29
+ a, b, c = ary
30
+
31
+ a.should be_nil
32
+ b.should be_nil
33
+ c.should be_nil
34
+ end
35
+
36
+ it "sets the splat to an empty Array if there are no more values" do
37
+ ary = []
38
+ a, b, *c = ary
39
+
40
+ a.should be_nil
41
+ b.should be_nil
42
+ c.should == []
43
+ end
44
+
45
+ it "allows multiple values to be assigned" do
46
+ a,b,*c = nil; [a,b,c].should == [nil, nil, []]
47
+ a,b,*c = 1; [a,b,c].should == [1, nil, []]
48
+ a,b,*c = []; [a,b,c].should == [nil, nil, []]
49
+ a,b,*c = [1]; [a,b,c].should == [1, nil, []]
50
+ a,b,*c = [nil]; [a,b,c].should == [nil, nil, []]
51
+ a,b,*c = [[]]; [a,b,c].should == [[], nil, []]
52
+ a,b,*c = [1,2]; [a,b,c].should == [1,2,[]]
53
+
54
+ a,b,*c = *nil; [a,b,c].should == [nil, nil, []]
55
+ a,b,*c = *[]; [a,b,c].should == [nil, nil, []]
56
+ a,b,*c = *[nil]; [a,b,c].should == [nil, nil, []]
57
+ a,b,*c = *[[]]; [a,b,c].should == [[], nil, []]
58
+ a,b,*c = *[1,2]; [a,b,c].should == [1,2,[]]
59
+ end
60
+
61
+ it "allows assignment through lambda" do
62
+ f = lambda {|r,*l| r.should == []; l.should == [1]}
63
+ f.call([], *[1])
64
+
65
+ f = lambda{|x| x}
66
+ f.call(42).should == 42
67
+ f.call([42]).should == [42]
68
+ f.call([[42]]).should == [[42]]
69
+ f.call([42,55]).should == [42,55]
70
+
71
+ f = lambda{|*x| x}
72
+ f.call(42).should == [42]
73
+ f.call([42]).should == [[42]]
74
+ f.call([[42]]).should == [[[42]]]
75
+ f.call([42,55]).should == [[42,55]]
76
+ f.call(42,55).should == [42,55]
77
+ end
78
+
79
+ it "allows chained assignment" do
80
+ (a = 1 + b = 2 + c = 4 + d = 8).should == 15
81
+ d.should == 8
82
+ c.should == 12
83
+ b.should == 14
84
+ a.should == 15
85
+ end
86
+ end
87
+
88
+ describe "Assignment using expansion" do
89
+ ruby_version_is "1.9" do
90
+ it "succeeds without conversion" do
91
+ *x = (1..7).to_a
92
+ x.should == [1, 2, 3, 4, 5, 6, 7]
93
+ end
94
+ end
26
95
  end
27
96
 
28
97
  describe "Assigning multiple values" do