Skip to content

Commit 99f51d1

Browse files
committedJul 30, 2013
Initial fixes for Singleton module
1 parent b05d6d2 commit 99f51d1

File tree

7 files changed

+99
-12
lines changed

7 files changed

+99
-12
lines changed
 

Diff for: ‎corelib/opal/runtime.js

+10
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,16 @@
296296
throw Opal.ArgumentError.$new(msg);
297297
};
298298

299+
// Super dispatcher
300+
Opal.dispatch_super = function(obj, jsid, args) {
301+
if (obj._isClass) {
302+
return obj._klass['$' + jsid].apply(obj, args);
303+
}
304+
else {
305+
return obj._klass._super._proto['$' + jsid].apply(obj, args);
306+
}
307+
};
308+
299309
/*
300310
Call a ruby method on a ruby object with some arguments:
301311

Diff for: ‎lib/opal/parser.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -2107,7 +2107,7 @@ def js_super args, sexp
21072107
if @scope.defs
21082108
[fragment(("%s._super%s.apply(this, " % [cls_name, jsid]), sexp), args, fragment(")", sexp)]
21092109
else
2110-
[fragment("#{current_self}._klass._super._proto#{jsid}.apply(#{current_self}, ", sexp), args, fragment(")", sexp)]
2110+
[fragment("__opal.dispatch_super(#{current_self}, #{@scope.mid.to_s.inspect}, ", sexp), args, fragment(")", sexp)]
21112111
end
21122112

21132113
elsif @scope.type == :iter

Diff for: ‎spec/rubyspec/library/singleton/clone_spec.rb

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
require File.expand_path('../../../spec_helper', __FILE__)
2+
require File.expand_path('../fixtures/classes', __FILE__)
3+
4+
describe "Singleton#clone" do
5+
it "is prevented" do
6+
lambda { SingletonSpecs::MyClass.instance.clone }.should raise_error(TypeError)
7+
end
8+
end

Diff for: ‎spec/rubyspec/library/singleton/dup_spec.rb

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
require File.expand_path('../../../spec_helper', __FILE__)
2+
require File.expand_path('../fixtures/classes', __FILE__)
3+
4+
describe "Singleton#dup" do
5+
it "is prevented" do
6+
lambda { SingletonSpecs::MyClass.instance.dup }.should raise_error(TypeError)
7+
end
8+
end

Diff for: ‎spec/rubyspec/library/singleton/fixtures/classes.rb

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
require 'singleton'
2+
3+
module SingletonSpecs
4+
class MyClass
5+
attr_accessor :data
6+
include Singleton
7+
end
8+
9+
class NewSpec
10+
include Singleton
11+
end
12+
13+
class MyClassChild < MyClass
14+
end
15+
16+
class NotInstantiated < MyClass
17+
end
18+
end

Diff for: ‎spec/rubyspec/library/singleton/instance_spec.rb

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
require File.expand_path('../../../spec_helper', __FILE__)
2+
require File.expand_path('../fixtures/classes', __FILE__)
3+
4+
describe "Singleton.instance" do
5+
it "returns an instance of the singleton class" do
6+
SingletonSpecs::MyClass.instance.should be_kind_of(SingletonSpecs::MyClass)
7+
end
8+
9+
it "returns the same instance for multiple calls to instance" do
10+
SingletonSpecs::MyClass.instance.should equal(SingletonSpecs::MyClass.instance)
11+
end
12+
13+
it "returns an instance of the singleton's subclasses" do
14+
SingletonSpecs::MyClassChild.instance.should be_kind_of(SingletonSpecs::MyClassChild)
15+
end
16+
17+
it "returns the same instance for multiple class to instance on subclasses" do
18+
SingletonSpecs::MyClassChild.instance.should equal(SingletonSpecs::MyClassChild.instance)
19+
end
20+
21+
pending "returns an instance of the singleton's clone" do
22+
klone = SingletonSpecs::MyClassChild.clone
23+
klone.instance.should be_kind_of(klone)
24+
end
25+
26+
pending "returns the same instance for multiple class to instance on clones" do
27+
klone = SingletonSpecs::MyClassChild.clone
28+
klone.instance.should equal(klone.instance)
29+
end
30+
end

Diff for: ‎stdlib/singleton.rb

+24-11
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,34 @@ def dup
77
raise TypeError, "can't dup instance of singleton #{self.class}"
88
end
99

10-
def self.included (klass)
11-
super
10+
module SingletonClassMethods
1211

13-
class << klass
14-
#def new
15-
#raise ArgumentError, "you can't call #new on a Singleton" if @instance
16-
17-
#@instance = super
18-
#end
12+
def clone
13+
Singleton.__init__(super)
14+
end
1915

20-
undef_method :allocate
16+
def inherited(sub_klass)
17+
super
18+
Singleton.__init__(sub_klass)
19+
end
20+
end
2121

22-
def instance
23-
@instance ||= new()
22+
class << Singleton
23+
def __init__(klass)
24+
klass.instance_eval {
25+
@singleton__instance__ = nil
26+
}
27+
def klass.instance
28+
return @singleton__instance__ if @singleton__instance__
29+
@singleton__instance__ = new()
2430
end
31+
klass
32+
end
33+
34+
def included(klass)
35+
super
36+
klass.extend SingletonClassMethods
37+
Singleton.__init__(klass)
2538
end
2639
end
2740
end

0 commit comments

Comments
 (0)
Please sign in to comment.