opal 0.3.37 → 0.3.38
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +11 -0
- data/Gemfile +0 -8
- data/README.md +7 -6
- data/bin/opal +18 -10
- data/config.ru +8 -21
- data/lib/assets/javascripts/opal-parser.js.erb +3 -60
- data/lib/assets/javascripts/opal/array.rb +87 -43
- data/lib/assets/javascripts/opal/basic_object.rb +4 -0
- data/lib/assets/javascripts/opal/boolean.rb +5 -3
- data/lib/assets/javascripts/opal/class.rb +19 -4
- data/lib/assets/javascripts/opal/comparable.rb +1 -1
- data/lib/assets/javascripts/opal/enumerable.rb +32 -0
- data/lib/assets/javascripts/opal/error.rb +1 -1
- data/lib/assets/javascripts/opal/hash.rb +166 -103
- data/lib/assets/javascripts/opal/json.rb +3 -2
- data/lib/assets/javascripts/opal/kernel.rb +9 -1
- data/lib/assets/javascripts/opal/native.rb +29 -0
- data/lib/assets/javascripts/opal/nil_class.rb +9 -1
- data/lib/assets/javascripts/opal/numeric.rb +6 -4
- data/lib/assets/javascripts/opal/parser.js +57 -0
- data/lib/assets/javascripts/opal/proc.rb +5 -5
- data/lib/assets/javascripts/opal/regexp.rb +1 -1
- data/lib/assets/javascripts/opal/runtime.js +13 -0
- data/lib/assets/javascripts/opal/string.rb +14 -3
- data/lib/assets/javascripts/opal/time.rb +1 -1
- data/lib/opal.rb +1 -1
- data/lib/opal/parser.rb +39 -13
- data/lib/opal/processor.rb +13 -2
- data/lib/opal/version.rb +1 -1
- data/opal.gemspec +3 -0
- data/spec/core/array/fill_spec.rb +26 -0
- data/spec/core/array/try_convert_spec.rb +15 -0
- data/spec/core/enumerable/each_slice_spec.rb +24 -0
- data/spec/core/enumerable/group_by_spec.rb +16 -0
- data/spec/core/module/const_get_spec.rb +34 -0
- data/spec/core/module/undef_method_spec.rb +67 -0
- data/spec/core/nil/to_h_spec.rb +10 -0
- data/spec/core/proc/element_reference_spec.rb +21 -0
- data/spec/{core → core_ext}/array/to_json_spec.rb +0 -0
- data/spec/core_ext/method_missing_spec.rb +43 -0
- data/spec/core_ext/native/fixtures/classes.rb +5 -0
- data/spec/core_ext/native/initialize_spec.rb +8 -0
- data/spec/core_ext/native/method_missing_spec.rb +7 -0
- data/spec/core_ext/native/to_native_spec.rb +7 -0
- data/spec/grammar/parser_spec.rb +1 -1
- data/spec/language/super_spec.rb +20 -0
- data/spec/language/variables_spec.rb +69 -0
- data/spec/spec_helper.rb +9 -5
- metadata +66 -8
- data/lib/assets/javascripts/opal/core.rb +0 -36
- data/spec/autorun.rb +0 -3
data/lib/opal/processor.rb
CHANGED
@@ -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
|
-
|
22
|
-
|
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
data/opal.gemspec
CHANGED
@@ -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,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
|
data/spec/grammar/parser_spec.rb
CHANGED
@@ -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("
|
25
|
+
opal_eval("Spec::ExampleGroup").should == Spec::ExampleGroup
|
26
26
|
end
|
27
27
|
|
28
28
|
it "should parse class and module definitions" do
|
data/spec/language/super_spec.rb
CHANGED
@@ -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
|