coderrr-mixico-inline 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
data/lib/mixico.rb CHANGED
@@ -3,7 +3,7 @@ require 'inline'
3
3
 
4
4
  class Module
5
5
  inline do |builder|
6
- builder.c %q{
6
+ builder.c %{
7
7
  static VALUE
8
8
  disable_mixin(VALUE super)
9
9
  {
@@ -25,7 +25,7 @@ class Module
25
25
  }
26
26
  }
27
27
 
28
- builder.c %q{
28
+ builder.c %{
29
29
  static VALUE
30
30
  enable_mixin(VALUE mixin)
31
31
  {
@@ -48,6 +48,58 @@ class Module
48
48
  end
49
49
  end
50
50
 
51
+ class Object
52
+ inline do |builder|
53
+ builder.prefix %{
54
+ #define KLASS_OF(o) RCLASS(RBASIC(o)->klass)
55
+ }
56
+
57
+ builder.c %{
58
+ void redirect_tbls(VALUE obj) {
59
+ unsigned long orig_iv_tbl, orig_m_tbl;
60
+ orig_iv_tbl = (unsigned long)ROBJECT(self)->iv_tbl;
61
+ orig_m_tbl = (unsigned long)KLASS_OF(self)->m_tbl;
62
+ ROBJECT(self)->iv_tbl = ROBJECT(obj)->iv_tbl;
63
+ KLASS_OF(self)->m_tbl = KLASS_OF(obj)->m_tbl;
64
+ rb_iv_set(self, "__orig_m_tbl__", orig_m_tbl);
65
+ rb_iv_set(self, "__orig_iv_tbl__", orig_iv_tbl);
66
+ }
67
+ }
68
+
69
+ # restore needed, or else GC will crash
70
+ builder.c %{
71
+ void restore_tbls() {
72
+ KLASS_OF(self)->m_tbl = (struct st_table *)rb_iv_get(self, "__orig_m_tbl__");
73
+ KLASS_OF(self)->iv_tbl = (struct st_table *)rb_iv_get(self, "__orig_iv_tbl__");
74
+ }
75
+ }
76
+ end
77
+ end
78
+
79
+ class Class
80
+ inline do |builder|
81
+ builder.c %{
82
+ void redirect_tbls(VALUE class) {
83
+ unsigned long orig_iv_tbl, orig_m_tbl;
84
+ orig_iv_tbl = (unsigned long)RCLASS(self)->iv_tbl;
85
+ orig_m_tbl = (unsigned long)RCLASS(self)->m_tbl;
86
+ RCLASS(self)->iv_tbl = RCLASS(class)->iv_tbl;
87
+ RCLASS(self)->m_tbl = RCLASS(class)->m_tbl;
88
+ rb_iv_set(self, "__orig_iv_tbl__", orig_iv_tbl);
89
+ rb_iv_set(self, "__orig_m_tbl__", orig_m_tbl);
90
+ }
91
+ }
92
+
93
+ # restore needed, or else GC will crash
94
+ builder.c %{
95
+ void restore_tbls() {
96
+ RCLASS(self)->m_tbl = rb_iv_get(self, "__orig_m_tbl__");
97
+ RCLASS(self)->iv_tbl = rb_iv_get(self, "__orig_iv_tbl__");
98
+ }
99
+ }
100
+ end
101
+ end
102
+
51
103
  class Proc
52
104
  def mixin mod
53
105
  context.extend mod
@@ -71,6 +123,23 @@ class Module
71
123
  blk.mixout mod
72
124
  end
73
125
  end
126
+
127
+ def safe_mix_eval mod, &blk
128
+ duped_context = blk.context.dup
129
+ # make sure the singleton class is in existence
130
+ class << duped_context; self; end
131
+
132
+ duped_context.redirect_tbls(blk.context)
133
+
134
+ duped_context.extend mod
135
+ begin
136
+ m = duped_context.is_a?(Module) ? :class_eval : :instance_eval
137
+ duped_context.send(m, &blk)
138
+ ensure
139
+ duped_context.restore_tbls
140
+ (class << duped_context; self; end).disable_mixin mod
141
+ end
142
+ end
74
143
 
75
144
  alias_method :mix_exec, :mix_eval
76
145
  end
@@ -1,7 +1,7 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "mixico-inline"
3
- s.version = "0.0.5"
4
- s.summary = "1.8.6 compatible version of why's mixico"
3
+ s.version = "0.0.6"
4
+ s.summary = "1.8.6 compatible version of why's mixico + thread safety"
5
5
  s.email = "coderrr.contact@gmail.com"
6
6
  s.homepage = "http://github.com/coderrr/mixico-inline"
7
7
  s.description = "see http://github.com/why/mixico"
data/test/mixico_test.rb CHANGED
@@ -32,4 +32,81 @@ class MixicoTest < Test::Unit::TestCase
32
32
  @p.mixout @m
33
33
  assert_raises(NameError) { @p.call }
34
34
  end
35
+
36
+ def test_mix_eval_modify_ivar
37
+ @x = 5
38
+ b = lambda do
39
+ assert_equal 5, @x
40
+ @x = 6
41
+ end
42
+ Module.mix_eval @m, &b
43
+ assert_equal 6, @x
44
+ end
45
+
46
+ def test_safe_mix_eval_modify_ivar
47
+ b = lambda do
48
+ assert_equal 5, @x
49
+ @x = 6
50
+ end
51
+ @x = 5
52
+ Module.safe_mix_eval @m, &b
53
+ assert_equal 6, @x
54
+ end
55
+
56
+ def test_mix_eval_add_method
57
+ k = Class.new
58
+ k.class_eval do
59
+ b = lambda do
60
+ def x; :x; end
61
+ end
62
+
63
+ Module.mix_eval Module.new, &b
64
+ end
65
+ assert_equal :x, k.new.x
66
+ end
67
+
68
+ def test_mix_eval_add_singleton_method
69
+ o = Object.new
70
+ o.instance_eval do
71
+ Module.mix_eval Module.new do
72
+ def x; :x; end
73
+ end
74
+ end
75
+ assert_equal :x, o.x
76
+ end
77
+
78
+ def test_safe_mix_eval_add_method
79
+ k = Class.new
80
+ k.class_eval do
81
+ Module.safe_mix_eval Module.new do
82
+ def x; :x; end
83
+ end
84
+ end
85
+ assert_equal :x, k.new.x
86
+ end
87
+
88
+ def test_safe_mix_eval_add_singleton_method
89
+ o = Object.new
90
+ o.instance_eval do
91
+ Module.safe_mix_eval Module.new do
92
+ def x; :x; end
93
+ end
94
+ end
95
+ assert_equal :x, o.x
96
+ end
97
+
98
+ def test_FIX_THIS_safe_mix_eval_add_singleton_method_in_class
99
+ k = Class.new
100
+ k.class_eval do
101
+ Module.safe_mix_eval Module.new do
102
+ class << self
103
+ def x; :x; end
104
+ end
105
+ end
106
+ end
107
+
108
+ # FIX THIS, THIS SHOULD NOT HAPPEN
109
+ assert_raises(NoMethodError) { k.x }
110
+ # assert_equal :x, k.x
111
+ end
35
112
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: coderrr-mixico-inline
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - why
@@ -60,6 +60,6 @@ rubyforge_project:
60
60
  rubygems_version: 1.2.0
61
61
  signing_key:
62
62
  specification_version: 2
63
- summary: 1.8.6 compatible version of why's mixico
63
+ summary: 1.8.6 compatible version of why's mixico + thread safety
64
64
  test_files:
65
65
  - test/mixico_test.rb