therubyracer 0.10.2 → 0.11.0beta1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of therubyracer might be problematic. Click here for more details.

Files changed (159) hide show
  1. data/.gitignore +21 -11
  2. data/.travis.yml +2 -1
  3. data/Changelog.md +46 -0
  4. data/Gemfile +16 -1
  5. data/README.md +31 -13
  6. data/Rakefile +42 -23
  7. data/benchmarks.rb +217 -0
  8. data/ext/v8/accessor.cc +181 -0
  9. data/ext/v8/array.cc +26 -0
  10. data/ext/v8/backref.cc +56 -0
  11. data/ext/v8/build.rb +51 -0
  12. data/ext/v8/constants.cc +34 -0
  13. data/ext/v8/constraints.cc +52 -0
  14. data/ext/v8/context.cc +130 -0
  15. data/ext/v8/date.cc +18 -0
  16. data/ext/v8/exception.cc +38 -0
  17. data/ext/v8/extconf.rb +14 -18
  18. data/ext/v8/external.cc +43 -0
  19. data/ext/v8/function.cc +58 -0
  20. data/ext/v8/gc.cc +43 -0
  21. data/ext/v8/handles.cc +34 -0
  22. data/ext/v8/heap.cc +31 -0
  23. data/ext/v8/init.cc +39 -0
  24. data/ext/v8/invocation.cc +86 -0
  25. data/ext/v8/locker.cc +77 -0
  26. data/ext/v8/message.cc +51 -0
  27. data/ext/v8/object.cc +334 -0
  28. data/ext/v8/primitive.cc +8 -0
  29. data/ext/v8/rr.cc +83 -0
  30. data/ext/v8/rr.h +878 -36
  31. data/ext/v8/script.cc +80 -0
  32. data/ext/v8/signature.cc +18 -0
  33. data/ext/v8/stack.cc +75 -0
  34. data/ext/v8/string.cc +47 -0
  35. data/ext/v8/template.cc +175 -0
  36. data/ext/v8/trycatch.cc +86 -0
  37. data/ext/v8/v8.cc +87 -0
  38. data/ext/v8/value.cc +239 -0
  39. data/lib/v8.rb +30 -22
  40. data/lib/v8/access.rb +5 -87
  41. data/lib/v8/access/indices.rb +40 -0
  42. data/lib/v8/access/invocation.rb +47 -0
  43. data/lib/v8/access/names.rb +65 -0
  44. data/lib/v8/array.rb +19 -10
  45. data/lib/v8/context.rb +85 -78
  46. data/lib/v8/conversion.rb +35 -0
  47. data/lib/v8/conversion/array.rb +11 -0
  48. data/lib/v8/conversion/class.rb +120 -0
  49. data/lib/v8/conversion/code.rb +38 -0
  50. data/lib/v8/conversion/fundamental.rb +11 -0
  51. data/lib/v8/conversion/hash.rb +11 -0
  52. data/lib/v8/conversion/indentity.rb +31 -0
  53. data/lib/v8/conversion/method.rb +26 -0
  54. data/lib/v8/conversion/object.rb +28 -0
  55. data/lib/v8/conversion/primitive.rb +7 -0
  56. data/lib/v8/conversion/proc.rb +5 -0
  57. data/lib/v8/conversion/reference.rb +16 -0
  58. data/lib/v8/conversion/string.rb +12 -0
  59. data/lib/v8/conversion/symbol.rb +7 -0
  60. data/lib/v8/conversion/time.rb +13 -0
  61. data/lib/v8/error.rb +18 -123
  62. data/lib/v8/error/protect.rb +20 -0
  63. data/lib/v8/error/try.rb +15 -0
  64. data/lib/v8/function.rb +18 -34
  65. data/lib/v8/object.rb +48 -52
  66. data/lib/v8/util/weakcell.rb +29 -0
  67. data/lib/v8/version.rb +2 -2
  68. data/spec/c/array_spec.rb +17 -0
  69. data/spec/c/constants_spec.rb +20 -0
  70. data/spec/c/exception_spec.rb +26 -0
  71. data/spec/c/external_spec.rb +9 -0
  72. data/spec/c/function_spec.rb +46 -0
  73. data/spec/c/handles_spec.rb +35 -0
  74. data/spec/c/locker_spec.rb +38 -0
  75. data/spec/c/object_spec.rb +46 -0
  76. data/spec/c/script_spec.rb +28 -0
  77. data/spec/c/string_spec.rb +16 -0
  78. data/spec/c/template_spec.rb +30 -0
  79. data/spec/c/trycatch_spec.rb +51 -0
  80. data/spec/mem/blunt_spec.rb +42 -0
  81. data/spec/redjs_spec.rb +10 -0
  82. data/spec/spec_helper.rb +40 -4
  83. data/spec/threading_spec.rb +52 -0
  84. data/spec/v8/context_spec.rb +19 -0
  85. data/spec/v8/conversion_spec.rb +9 -0
  86. data/spec/v8/error_spec.rb +15 -125
  87. data/spec/v8/function_spec.rb +9 -0
  88. data/therubyracer.gemspec +15 -24
  89. metadata +102 -135
  90. data/.gitmodules +0 -3
  91. data/.rspec +0 -1
  92. data/.yardopts +0 -1
  93. data/bin/therubyracer +0 -11
  94. data/ext/v8/rr.cpp +0 -189
  95. data/ext/v8/v8.cpp +0 -48
  96. data/ext/v8/v8_array.cpp +0 -48
  97. data/ext/v8/v8_array.h +0 -8
  98. data/ext/v8/v8_callbacks.cpp +0 -81
  99. data/ext/v8/v8_callbacks.h +0 -8
  100. data/ext/v8/v8_context.cpp +0 -92
  101. data/ext/v8/v8_context.h +0 -6
  102. data/ext/v8/v8_date.cpp +0 -34
  103. data/ext/v8/v8_date.h +0 -6
  104. data/ext/v8/v8_debug.cpp +0 -17
  105. data/ext/v8/v8_debug.h +0 -6
  106. data/ext/v8/v8_exception.cpp +0 -133
  107. data/ext/v8/v8_exception.h +0 -11
  108. data/ext/v8/v8_external.cpp +0 -70
  109. data/ext/v8/v8_external.h +0 -8
  110. data/ext/v8/v8_function.cpp +0 -69
  111. data/ext/v8/v8_function.h +0 -11
  112. data/ext/v8/v8_handle.cpp +0 -186
  113. data/ext/v8/v8_handle.h +0 -48
  114. data/ext/v8/v8_locker.cpp +0 -139
  115. data/ext/v8/v8_locker.h +0 -6
  116. data/ext/v8/v8_message.cpp +0 -67
  117. data/ext/v8/v8_message.h +0 -10
  118. data/ext/v8/v8_object.cpp +0 -122
  119. data/ext/v8/v8_object.h +0 -10
  120. data/ext/v8/v8_script.cpp +0 -36
  121. data/ext/v8/v8_script.h +0 -8
  122. data/ext/v8/v8_string.cpp +0 -52
  123. data/ext/v8/v8_string.h +0 -9
  124. data/ext/v8/v8_template.cpp +0 -344
  125. data/ext/v8/v8_template.h +0 -8
  126. data/ext/v8/v8_try_catch.cpp +0 -70
  127. data/ext/v8/v8_try_catch.h +0 -5
  128. data/ext/v8/v8_v8.cpp +0 -35
  129. data/ext/v8/v8_v8.h +0 -6
  130. data/ext/v8/v8_value.cpp +0 -175
  131. data/ext/v8/v8_value.h +0 -10
  132. data/ext/v8/v8_weakref.cpp +0 -61
  133. data/ext/v8/v8_weakref.h +0 -29
  134. data/lib/v8/c/locker.rb +0 -18
  135. data/lib/v8/cli.rb +0 -133
  136. data/lib/v8/portal.rb +0 -86
  137. data/lib/v8/portal/caller.rb +0 -37
  138. data/lib/v8/portal/constructor.rb +0 -98
  139. data/lib/v8/portal/function.rb +0 -63
  140. data/lib/v8/portal/interceptors.rb +0 -152
  141. data/lib/v8/portal/proxies.rb +0 -151
  142. data/lib/v8/portal/templates.rb +0 -73
  143. data/lib/v8/stack.rb +0 -66
  144. data/lib/v8/tap.rb +0 -9
  145. data/spec/ext/array_spec.rb +0 -15
  146. data/spec/ext/cxt_spec.rb +0 -57
  147. data/spec/ext/ext_spec_helper.rb +0 -27
  148. data/spec/ext/func_spec.rb +0 -64
  149. data/spec/ext/object_spec.rb +0 -10
  150. data/spec/ext/string_spec.rb +0 -11
  151. data/spec/ext/try_catch_spec.rb +0 -60
  152. data/spec/redjs_helper.rb +0 -3
  153. data/spec/v8/portal/proxies_spec.rb +0 -106
  154. data/specmem/handle_memspec.rb +0 -41
  155. data/specmem/object_memspec.rb +0 -14
  156. data/specmem/proxies_memspec.rb +0 -49
  157. data/specmem/spec_helper.rb +0 -24
  158. data/specthread/spec_helper.rb +0 -2
  159. data/specthread/threading_spec.rb +0 -13
@@ -0,0 +1,40 @@
1
+ class V8::Access
2
+ module Indices
3
+
4
+ def indices(obj)
5
+ obj.respond_to?(:length) ? (0..obj.length).to_a : []
6
+ end
7
+
8
+ def iget(obj, index, &dontintercept)
9
+ if obj.respond_to?(:[])
10
+ obj.send(:[], index, &dontintercept)
11
+ else
12
+ yield
13
+ end
14
+ end
15
+
16
+ def iset(obj, index, value, &dontintercept)
17
+ if obj.respond_to?(:[]=)
18
+ obj.send(:[]=, index, value, &dontintercept)
19
+ else
20
+ yield
21
+ end
22
+ end
23
+
24
+ def iquery(obj, index, attributes, &dontintercept)
25
+ if obj.respond_to?(:[])
26
+ attributes.dont_delete
27
+ unless obj.respond_to?(:[]=)
28
+ attributes.read_only
29
+ end
30
+ else
31
+ yield
32
+ end
33
+ end
34
+
35
+ def idelete(obj, index, &dontintercept)
36
+ yield
37
+ end
38
+
39
+ end
40
+ end
@@ -0,0 +1,47 @@
1
+ class V8::Access
2
+ module Invocation
3
+ def methodcall(code, this, args)
4
+ code.methodcall this, args
5
+ end
6
+
7
+ module Aritize
8
+ def aritize(args)
9
+ arity < 0 ? args : Array.new(arity).to_enum(:each_with_index).map {|item, i| args[i]}
10
+ end
11
+ end
12
+
13
+ module Proc
14
+ include Aritize
15
+ def methodcall(this, args)
16
+ call *aritize([this].concat(args))
17
+ end
18
+ ::Proc.send :include, self
19
+ end
20
+
21
+ module Method
22
+ include Aritize
23
+ def methodcall(this, args)
24
+ context = V8::Context.current
25
+ access = context.access
26
+ if this.equal? self.receiver
27
+ call *aritize(args)
28
+ elsif this.class <= self.receiver.class
29
+ access.methodcall(unbind, this, args)
30
+ elsif this.equal? context.scope
31
+ call *aritize(args)
32
+ else
33
+ fail TypeError, "cannot invoke #{self} on #{this}"
34
+ end
35
+ end
36
+ ::Method.send :include, self
37
+ end
38
+
39
+ module UnboundMethod
40
+ def methodcall(this, args)
41
+ access = V8::Context.current.access
42
+ access.methodcall bind(this), this, args
43
+ end
44
+ ::UnboundMethod.send :include, self
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,65 @@
1
+ require 'set'
2
+ class V8::Access
3
+ module Names
4
+ def names(obj)
5
+ accessible_names(obj)
6
+ end
7
+
8
+ def get(obj, name, &dontintercept)
9
+ methods = accessible_names(obj)
10
+ if methods.include?(name)
11
+ method = obj.method(name)
12
+ method.arity == 0 ? method.call : method.unbind
13
+ elsif obj.respond_to?(:[]) && !special?(name)
14
+ obj.send(:[], name, &dontintercept)
15
+ else
16
+ yield
17
+ end
18
+ end
19
+
20
+ def set(obj, name, value, &dontintercept)
21
+ setter = name + "="
22
+ methods = accessible_names(obj, true)
23
+ if methods.include?(setter)
24
+ obj.send(setter, value)
25
+ elsif obj.respond_to?(:[]=) && !special?(name)
26
+ obj.send(:[]=, name, value, &dontintercept)
27
+ else
28
+ yield
29
+ end
30
+ end
31
+
32
+ def query(obj, name, attributes, &dontintercept)
33
+ if obj.respond_to?(name)
34
+ attributes.dont_delete
35
+ unless obj.respond_to?(name + "=")
36
+ attributes.read_only
37
+ end
38
+ else
39
+ yield
40
+ end
41
+ end
42
+
43
+ def delete(obj, name, &dontintercept)
44
+ yield
45
+ end
46
+
47
+ def accessible_names(obj, special_methods = false)
48
+ obj.public_methods(false).map {|m| m.to_s}.to_set.tap do |methods|
49
+ ancestors = obj.class.ancestors.dup
50
+ while ancestor = ancestors.shift
51
+ break if ancestor == ::Object
52
+ methods.merge(ancestor.public_instance_methods(false).map {|m| m.to_s})
53
+ end
54
+ methods.reject!(&special?) unless special_methods
55
+ end
56
+ end
57
+
58
+ private
59
+
60
+ def special?(name = nil)
61
+ @special ||= lambda {|m| m == "[]" || m == "[]=" || m =~ /=$/}
62
+ name.nil? ? @special : @special[name]
63
+ end
64
+ end
65
+ end
data/lib/v8/array.rb CHANGED
@@ -1,17 +1,26 @@
1
+ class V8::Array < V8::Object
1
2
 
2
- module V8
3
- class Array < V8::Object
4
-
5
- def each
6
- @portal.open do |to|
7
- for i in 0..(@native.Length() - 1)
8
- yield to.rb(@native.Get(i))
9
- end
3
+ def initialize(native_or_length = nil)
4
+ super do
5
+ if native_or_length.is_a?(Numeric)
6
+ V8::C::Array::New(native_or_length)
7
+ elsif native_or_length.is_a?(V8::C::Array)
8
+ native_or_length
9
+ else
10
+ V8::C::Array::New()
10
11
  end
11
12
  end
13
+ end
12
14
 
13
- def length
14
- @native.Length()
15
+ def each
16
+ @context.enter do
17
+ 0.upto(@native.Length() - 1) do |i|
18
+ yield @context.to_ruby(@native.Get(i))
19
+ end
15
20
  end
16
21
  end
22
+
23
+ def length
24
+ @native.Length()
25
+ end
17
26
  end
data/lib/v8/context.rb CHANGED
@@ -1,111 +1,118 @@
1
1
  require 'stringio'
2
-
3
2
  module V8
4
3
  class Context
5
- attr_reader :native, :scope, :access
4
+ include V8::Error::Try
5
+ attr_reader :native, :conversion, :access
6
6
 
7
- def initialize(opts = {})
7
+ def initialize(options = {})
8
+ @conversion = Conversion.new
8
9
  @access = Access.new
9
- @to = Portal.new(self, @access)
10
- @to.lock do
11
- with = opts[:with]
12
- constructor = nil
13
- template = if with
14
- constructor = @to.templates.to_constructor(with.class)
15
- constructor.disable()
16
- constructor.template.InstanceTemplate()
17
- else
18
- C::ObjectTemplate::New()
19
- end
20
- @native = opts[:with] ? C::Context::New(template) : C::Context::New()
21
- @native.enter do
22
- @global = @native.Global()
23
- @to.proxies.register_javascript_proxy @global, :for => with if with
24
- constructor.enable() if constructor
25
- @scope = @to.rb(@global)
26
- @global.SetHiddenValue(C::String::NewSymbol("TheRubyRacer::RubyContext"), C::External::New(self))
10
+ if global = options[:with]
11
+ Context.new.enter do
12
+ global_template = global.class.to_template.InstanceTemplate()
13
+ @native = V8::C::Context::New(nil, global_template)
27
14
  end
28
- yield(self) if block_given?
15
+ enter {link global, @native.Global()}
16
+ else
17
+ @native = V8::C::Context::New()
29
18
  end
19
+ yield self if block_given?
30
20
  end
31
21
 
32
- def eval(javascript, filename = "<eval>", line = 1)
33
- if IO === javascript || StringIO === javascript
34
- javascript = javascript.read()
22
+ def eval(source, filename = '<eval>', line = 1)
23
+ if IO === source || StringIO === source
24
+ source = source.read
35
25
  end
36
- err = nil
37
- value = nil
38
- @to.lock do
39
- C::TryCatch.try do |try|
40
- @native.enter do
41
- script = C::Script::Compile(@to.v8(javascript.to_s), @to.v8(filename.to_s))
42
- if try.HasCaught()
43
- err = JSError.new(try, @to)
44
- else
45
- result = script.Run()
46
- if try.HasCaught()
47
- err = JSError.new(try, @to)
48
- else
49
- value = @to.rb(result)
50
- end
51
- end
52
- end
53
- end
54
- end
55
- raise err if err
56
- return value
57
- end
58
-
59
- def load(filename)
60
- File.open(filename) do |file|
61
- self.eval file, filename, 1
26
+ enter do
27
+ script = try { V8::C::Script::New(source.to_s, filename.to_s) }
28
+ to_ruby try {script.Run()}
62
29
  end
63
30
  end
64
31
 
65
32
  def [](key)
66
- @to.open do
67
- @to.rb @global.Get(@to.v8(key))
33
+ enter do
34
+ to_ruby(@native.Global().Get(to_v8(key)))
68
35
  end
69
36
  end
70
37
 
71
38
  def []=(key, value)
72
- @to.open do
73
- @global.Set(@to.v8(key), @to.v8(value))
39
+ enter do
40
+ @native.Global().Set(to_v8(key), to_v8(value))
74
41
  end
75
42
  return value
76
43
  end
77
44
 
78
- def self.stack(limit = 99)
79
- if native = C::Context::GetEntered()
80
- global = native.Global()
81
- cxt = global.GetHiddenValue(C::String::NewSymbol("TheRubyRacer::RubyContext")).Value()
82
- cxt.instance_eval {@to.rb(C::StackTrace::CurrentStackTrace(limit))}
45
+ def dispose
46
+ return unless @native
47
+ @native.Dispose()
48
+ @native = nil
49
+ V8::C::V8::ContextDisposedNotification()
50
+ def self.enter
51
+ fail "cannot enter a context which has already been disposed"
52
+ end
53
+ end
54
+
55
+ def scope
56
+ enter { to_ruby @native.Global() }
57
+ end
58
+
59
+ def to_ruby(v8_object)
60
+ @conversion.to_ruby(v8_object)
61
+ end
62
+
63
+ def to_v8(ruby_object)
64
+ @conversion.to_v8(ruby_object)
65
+ end
66
+
67
+ def link(ruby_object, v8_object)
68
+ @conversion.equate ruby_object, v8_object
69
+ end
70
+
71
+ def self.link(*args)
72
+ current.link *args
73
+ end
74
+
75
+ def enter(&block)
76
+ if !entered?
77
+ lock_scope_and_enter(&block)
83
78
  else
84
- []
79
+ yield
85
80
  end
86
81
  end
87
-
88
- def self.passes_this_argument?
89
- true
82
+
83
+ def entered?
84
+ Context.current == self
90
85
  end
91
- end
92
86
 
93
- module C
94
- class Context
95
- def enter
96
- if block_given?
97
- if IsEntered()
98
- yield(self)
99
- else
100
- Enter()
101
- begin
102
- yield(self)
103
- ensure
104
- Exit()
105
- end
87
+ def self.current
88
+ Thread.current[:v8_context]
89
+ end
90
+
91
+ def self.current=(context)
92
+ Thread.current[:v8_context] = context
93
+ end
94
+
95
+ def lock_scope_and_enter
96
+ current = Context.current
97
+ Context.current = self
98
+ V8::C::Locker() do
99
+ V8::C::HandleScope() do
100
+ begin
101
+ @native.Enter()
102
+ yield if block_given?
103
+ ensure
104
+ @native.Exit()
106
105
  end
107
106
  end
108
107
  end
108
+ ensure
109
+ Context.current = current
110
+ end
111
+
112
+ def load(filename)
113
+ File.open(filename) do |file|
114
+ self.eval file, filename
115
+ end
109
116
  end
110
117
  end
111
118
  end
@@ -0,0 +1,35 @@
1
+
2
+ class V8::Conversion
3
+ include Fundamental
4
+ include Identity
5
+
6
+ def to_ruby(v8_object)
7
+ super v8_object
8
+ end
9
+
10
+ def to_v8(ruby_object)
11
+ super ruby_object
12
+ end
13
+ end
14
+
15
+ for type in [TrueClass, FalseClass, NilClass, Float, Fixnum] do
16
+ type.class_eval do
17
+ include V8::Conversion::Primitive
18
+ end
19
+ end
20
+
21
+ for type in [Class, Object, Array, Hash, String, Symbol, Time, Proc, Method] do
22
+ type.class_eval do
23
+ include V8::Conversion.const_get(name)
24
+ end
25
+ end
26
+ class UnboundMethod
27
+ include V8::Conversion::Method
28
+ end
29
+
30
+ for type in [:Object, :String, :Date] do
31
+ V8::C::const_get(type).class_eval do
32
+ include V8::Conversion::const_get("Native#{type}")
33
+ end
34
+ end
35
+
@@ -0,0 +1,11 @@
1
+ class V8::Conversion
2
+ module Array
3
+ def to_v8
4
+ array = V8::Array.new(length)
5
+ each_with_index do |item, i|
6
+ array[i] = item
7
+ end
8
+ return array.to_v8
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,120 @@
1
+ class V8::Conversion
2
+ module Class
3
+ include V8::Conversion::Code
4
+
5
+ def to_template
6
+ weakcell(:constructor) do
7
+ template = V8::C::FunctionTemplate::New(Constructor.new(self))
8
+ prototype = template.InstanceTemplate()
9
+ prototype.SetNamedPropertyHandler(Get, Set)
10
+ prototype.SetIndexedPropertyHandler(IGet, ISet)
11
+ if self != ::Object && superclass != ::Object && superclass != ::Class
12
+ template.Inherit(superclass.to_template)
13
+ end
14
+ template
15
+ end
16
+ end
17
+
18
+ class Constructor
19
+ include V8::Error::Protect
20
+
21
+ def initialize(cls)
22
+ @class = cls
23
+ end
24
+
25
+ def call(arguments)
26
+ arguments.extend Args
27
+ protect do
28
+ if arguments.linkage_call?
29
+ arguments.link
30
+ else
31
+ arguments.construct @class
32
+ end
33
+ end
34
+ return arguments.This()
35
+ end
36
+
37
+ module Args
38
+ def linkage_call?
39
+ self.Length() == 1 && self[0].IsExternal()
40
+ end
41
+
42
+ def link
43
+ external = self[0]
44
+ This().SetHiddenValue("rr::implementation", external)
45
+ context.link external.Value(), This()
46
+ end
47
+
48
+ def construct(cls)
49
+ context.link cls.new(*to_args), This()
50
+ end
51
+
52
+ def context
53
+ V8::Context.current
54
+ end
55
+
56
+ def to_args
57
+ args = ::Array.new(Length())
58
+ 0.upto(args.length - 1) do |i|
59
+ args[i] = self[i]
60
+ end
61
+ return args
62
+ end
63
+ end
64
+ end
65
+
66
+ module Accessor
67
+ include V8::Error::Protect
68
+ def intercept(info, key, &block)
69
+ context = V8::Context.current
70
+ access = context.access
71
+ object = context.to_ruby(info.This())
72
+ handles_property = true
73
+ dontintercept = proc do
74
+ handles_property = false
75
+ end
76
+ protect do
77
+ result = block.call(context, access, object, context.to_ruby(key), dontintercept)
78
+ handles_property ? context.to_v8(result) : V8::C::Value::Empty
79
+ end
80
+ end
81
+ end
82
+
83
+ class Get
84
+ extend Accessor
85
+ def self.call(property, info)
86
+ intercept(info, property) do |context, access, object, key, dontintercept|
87
+ access.get(object, key, &dontintercept)
88
+ end
89
+ end
90
+ end
91
+
92
+ class Set
93
+ extend Accessor
94
+ def self.call(property, value, info)
95
+ intercept(info, property) do |context, access, object, key, dontintercept|
96
+ access.set(object, key, context.to_ruby(value), &dontintercept)
97
+ end
98
+ end
99
+ end
100
+
101
+ class IGet
102
+ extend Accessor
103
+ def self.call(property, info)
104
+ intercept(info, property) do |context, access, object, key, dontintercept|
105
+ access.iget(object, key, &dontintercept)
106
+ end
107
+ end
108
+ end
109
+
110
+ class ISet
111
+ extend Accessor
112
+ def self.call(property, value, info)
113
+ intercept(info, property) do |context, access, object, key, dontintercept|
114
+ access.iset(object, key, context.to_ruby(value), &dontintercept)
115
+ end
116
+ end
117
+ end
118
+
119
+ end
120
+ end