diff --git a/lib/opal/grammar.rb b/lib/opal/grammar.rb index 0e4b24c490..07f1ec9158 100644 --- a/lib/opal/grammar.rb +++ b/lib/opal/grammar.rb @@ -2024,7 +2024,7 @@ class Grammar < Racc::Parser 3, 152, :_reduce_86, 3, 152, :_reduce_87, 3, 152, :_reduce_88, - 2, 152, :_reduce_none, + 2, 152, :_reduce_89, 1, 152, :_reduce_none, 1, 180, :_reduce_none, 2, 181, :_reduce_92, @@ -3328,7 +3328,11 @@ def _reduce_88(val, _values, result) result end -# reduce 89 omitted +def _reduce_89(val, _values, result) + result = s(:colon3, val[1].intern) + + result +end # reduce 90 omitted diff --git a/lib/opal/grammar.y b/lib/opal/grammar.y index 60c1927bcd..cb48063216 100644 --- a/lib/opal/grammar.y +++ b/lib/opal/grammar.y @@ -363,6 +363,9 @@ lhs: result = s(:colon2, val[0], val[2].intern) } | '::@' CONSTANT + { + result = s(:colon3, val[1].intern) + } | backref cname: diff --git a/lib/opal/grammar_helpers.rb b/lib/opal/grammar_helpers.rb index 91200d16f1..5a09630df4 100644 --- a/lib/opal/grammar_helpers.rb +++ b/lib/opal/grammar_helpers.rb @@ -222,6 +222,10 @@ def new_assign(lhs, rhs) lhs << rhs lhs[0] = :casgn lhs + when :colon3 + lhs << rhs + lhs[0] = :casgn3 + lhs else raise "Bad lhs for new_assign: #{lhs[0]}" end diff --git a/lib/opal/parser.rb b/lib/opal/parser.rb index bb24d37622..7831f2ae00 100644 --- a/lib/opal/parser.rb +++ b/lib/opal/parser.rb @@ -2049,6 +2049,11 @@ def process_colon3(exp, level) end end + def process_casgn3(sexp, level) + cid, rhs = sexp + [f("$opal.Object._scope.#{cid} = "), process(rhs)] + end + # super a, b, c # # s(:super, arg1, arg2, ...) diff --git a/spec/filters/bugs/class.rb b/spec/filters/bugs/class.rb new file mode 100644 index 0000000000..a92dc4af75 --- /dev/null +++ b/spec/filters/bugs/class.rb @@ -0,0 +1,6 @@ +opal_filter "Class" do + fails "Class.new raises a TypeError if passed a metaclass" + fails "Class.new creates a class that can be given a name by assigning it to a constant" + fails "Class.new raises a TypeError when given a non-Class" + fails "Class#new passes the block to #initialize" +end diff --git a/spec/rubyspec/core/class/fixtures/classes.rb b/spec/rubyspec/core/class/fixtures/classes.rb deleted file mode 100644 index a644035e93..0000000000 --- a/spec/rubyspec/core/class/fixtures/classes.rb +++ /dev/null @@ -1,9 +0,0 @@ -module CoreClassSpecs - module Inherited - class D - def self.inherited(subclass) - ScratchPad << self - end - end - end -end \ No newline at end of file diff --git a/spec/rubyspec/core/class/new_spec.rb b/spec/rubyspec/core/class/new_spec.rb deleted file mode 100644 index e79ecac10c..0000000000 --- a/spec/rubyspec/core/class/new_spec.rb +++ /dev/null @@ -1,113 +0,0 @@ -require File.expand_path('../../../spec_helper', __FILE__) -require File.expand_path('../fixtures/classes', __FILE__) - -describe "Class.new with a block given" do - it "uses the given block as the class' body" do - klass = Class.new do - def self.message - "text" - end - - def hello - "hello again" - end - end - - klass.message.should == "text" - klass.new.hello.should == "hello again" - end - - it "creates a subclass of the given superclass" do - sc = Class.new do - def self.body - @body - end - @body = self - def message; "text"; end - end - klass = Class.new(sc) do - def self.body - @body - end - @body = self - def message2; "hello"; end - end - - klass.body.should == klass - sc.body.should == sc - klass.superclass.should == sc - klass.new.message.should == "text" - klass.new.message2.should == "hello" - end - - it "runs the inherited hook after yielding the block" do - ScratchPad.record [] - klass = Class.new(CoreClassSpecs::Inherited::D) do - ScratchPad << self - end - - ScratchPad.recorded.should == [CoreClassSpecs::Inherited::D, klass] - end -end - -describe "Class.new" do - it "creates a new anonymous class" do - klass = Class.new - klass.is_a?(Class).should == true - - klass_instance = klass.new - klass_instance.is_a?(klass).should == true - end - - it "creates a class without a name" do - Class.new.name.should be_nil - end - - it "sets the new class' superclass to the given class" do - top = Class.new - Class.new(top).superclass.should == top - end - - it "sets the new class' superclass to Object when no class given" do - Class.new.superclass.should == Object - end -end - -describe "Class#new" do - it "returns a new instance of self" do - klass = Class.new - klass.new.is_a?(klass).should == true - end - - it "invokes #initialize on the new instance with the given args" do - klass = Class.new do - def initialize(*args) - @initialized = true - @args = args - end - - def args - @args - end - - def initialized? - @initialized || false - end - end - - klass.new.initialized?.should == true - klass.new(1, 2, 3).args.should == [1, 2, 3] - end - - it "passes the block to #initialize" do - lambda { - klass = Class.new do - def initialize(&block) - raise "no block given" unless block_given? - end - end - - klass.new { 42 } - }.should_not raise_error(Exception) - end -end diff --git a/spec/rubyspecs b/spec/rubyspecs index b7da29ed79..272c57d5e5 100644 --- a/spec/rubyspecs +++ b/spec/rubyspecs @@ -229,3 +229,4 @@ core/matchdata/to_a_spec core/range/begin_spec core/range/end_spec core/symbol/to_proc_spec +core/class/new_spec