coderrr-mixico-inline 0.0.5 → 0.0.6

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/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