opal 0.3.37 → 0.3.38
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.
- 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
|