therubyracer-freebsd 0.10.1
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/.gitignore +13 -0
- data/.rspec +1 -0
- data/.travis.yml +8 -0
- data/.yardopts +1 -0
- data/Changelog.md +231 -0
- data/Gemfile +3 -0
- data/README.md +167 -0
- data/Rakefile +26 -0
- data/bin/therubyracer +11 -0
- data/ext/v8/extconf.rb +26 -0
- data/ext/v8/rr.cpp +189 -0
- data/ext/v8/rr.h +41 -0
- data/ext/v8/v8.cpp +48 -0
- data/ext/v8/v8_array.cpp +48 -0
- data/ext/v8/v8_array.h +8 -0
- data/ext/v8/v8_callbacks.cpp +81 -0
- data/ext/v8/v8_callbacks.h +8 -0
- data/ext/v8/v8_context.cpp +92 -0
- data/ext/v8/v8_context.h +6 -0
- data/ext/v8/v8_date.cpp +40 -0
- data/ext/v8/v8_date.h +6 -0
- data/ext/v8/v8_debug.cpp +17 -0
- data/ext/v8/v8_debug.h +6 -0
- data/ext/v8/v8_exception.cpp +133 -0
- data/ext/v8/v8_exception.h +11 -0
- data/ext/v8/v8_external.cpp +70 -0
- data/ext/v8/v8_external.h +8 -0
- data/ext/v8/v8_function.cpp +69 -0
- data/ext/v8/v8_function.h +11 -0
- data/ext/v8/v8_handle.cpp +186 -0
- data/ext/v8/v8_handle.h +48 -0
- data/ext/v8/v8_locker.cpp +139 -0
- data/ext/v8/v8_locker.h +6 -0
- data/ext/v8/v8_message.cpp +67 -0
- data/ext/v8/v8_message.h +10 -0
- data/ext/v8/v8_object.cpp +122 -0
- data/ext/v8/v8_object.h +10 -0
- data/ext/v8/v8_script.cpp +36 -0
- data/ext/v8/v8_script.h +8 -0
- data/ext/v8/v8_string.cpp +52 -0
- data/ext/v8/v8_string.h +9 -0
- data/ext/v8/v8_template.cpp +344 -0
- data/ext/v8/v8_template.h +8 -0
- data/ext/v8/v8_try_catch.cpp +70 -0
- data/ext/v8/v8_try_catch.h +5 -0
- data/ext/v8/v8_v8.cpp +34 -0
- data/ext/v8/v8_v8.h +6 -0
- data/ext/v8/v8_value.cpp +175 -0
- data/ext/v8/v8_value.h +10 -0
- data/ext/v8/v8_weakref.cpp +61 -0
- data/ext/v8/v8_weakref.h +29 -0
- data/lib/v8.rb +23 -0
- data/lib/v8/access.rb +92 -0
- data/lib/v8/array.rb +17 -0
- data/lib/v8/c/locker.rb +18 -0
- data/lib/v8/cli.rb +133 -0
- data/lib/v8/context.rb +111 -0
- data/lib/v8/error.rb +130 -0
- data/lib/v8/function.rb +44 -0
- data/lib/v8/object.rb +69 -0
- data/lib/v8/portal.rb +86 -0
- data/lib/v8/portal/caller.rb +37 -0
- data/lib/v8/portal/constructor.rb +98 -0
- data/lib/v8/portal/function.rb +63 -0
- data/lib/v8/portal/interceptors.rb +152 -0
- data/lib/v8/portal/proxies.rb +151 -0
- data/lib/v8/portal/templates.rb +73 -0
- data/lib/v8/stack.rb +66 -0
- data/lib/v8/tap.rb +9 -0
- data/lib/v8/version.rb +3 -0
- data/spec/ext/array_spec.rb +15 -0
- data/spec/ext/cxt_spec.rb +57 -0
- data/spec/ext/ext_spec_helper.rb +27 -0
- data/spec/ext/func_spec.rb +64 -0
- data/spec/ext/object_spec.rb +10 -0
- data/spec/ext/string_spec.rb +11 -0
- data/spec/ext/try_catch_spec.rb +60 -0
- data/spec/redjs_spec.rb +9 -0
- data/spec/spec_helper.rb +9 -0
- data/spec/v8/error_spec.rb +131 -0
- data/spec/v8/portal/proxies_spec.rb +106 -0
- data/specmem/handle_memspec.rb +41 -0
- data/specmem/object_memspec.rb +14 -0
- data/specmem/proxies_memspec.rb +49 -0
- data/specmem/spec_helper.rb +24 -0
- data/specthread/spec_helper.rb +2 -0
- data/specthread/threading_spec.rb +13 -0
- data/thefrontside.png +0 -0
- data/therubyracer.gemspec +27 -0
- metadata +183 -0
data/lib/v8/object.rb
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
|
2
|
+
module V8
|
3
|
+
class Object
|
4
|
+
include Enumerable
|
5
|
+
|
6
|
+
def initialize(native, portal)
|
7
|
+
@native, @portal = native, portal
|
8
|
+
end
|
9
|
+
|
10
|
+
def [](key)
|
11
|
+
@portal.open do |to|
|
12
|
+
to.rb(@native.Get(to.v8(key)))
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def []=(key, value)
|
17
|
+
value.tap do
|
18
|
+
@portal.open do |to|
|
19
|
+
@native.Set(to.v8(key), to.v8(value))
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_s
|
25
|
+
@portal.open do |to|
|
26
|
+
to.rb(@native.ToString())
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def each
|
31
|
+
@portal.open do |to|
|
32
|
+
for prop in to.rb(@native.GetPropertyNames())
|
33
|
+
yield prop, self[prop]
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def respond_to?(method)
|
39
|
+
super or self[method] != nil
|
40
|
+
end
|
41
|
+
|
42
|
+
def method_missing(name, *args, &block)
|
43
|
+
if name.to_s =~ /(.*)=$/
|
44
|
+
if args.length > 1
|
45
|
+
self[$1] = args
|
46
|
+
return args
|
47
|
+
else
|
48
|
+
self[$1] = args.first
|
49
|
+
return args
|
50
|
+
end
|
51
|
+
end
|
52
|
+
return super(name, *args, &block) unless self.respond_to?(name)
|
53
|
+
property = self[name]
|
54
|
+
if property.kind_of?(V8::Function)
|
55
|
+
property.methodcall(self, *args)
|
56
|
+
elsif args.empty?
|
57
|
+
property
|
58
|
+
else
|
59
|
+
raise ArgumentError, "wrong number of arguments (#{args.length} for 0)" unless args.empty?
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
class Object
|
66
|
+
def eval_js(javascript)
|
67
|
+
V8::Context.new(:with => self).eval(javascript)
|
68
|
+
end
|
69
|
+
end
|
data/lib/v8/portal.rb
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
|
2
|
+
module V8
|
3
|
+
class Portal
|
4
|
+
attr_reader :context, :access, :proxies, :templates, :interceptors, :caller
|
5
|
+
|
6
|
+
def initialize(context, access)
|
7
|
+
@context, @access = context, access
|
8
|
+
@proxies = Proxies.new
|
9
|
+
@templates = Templates.new(self)
|
10
|
+
@interceptors = Interceptors.new(self)
|
11
|
+
@caller = Caller.new(self)
|
12
|
+
end
|
13
|
+
|
14
|
+
def lock
|
15
|
+
lock = V8::C::Locker.new
|
16
|
+
yield
|
17
|
+
ensure
|
18
|
+
lock.delete
|
19
|
+
end
|
20
|
+
|
21
|
+
def open
|
22
|
+
lock do
|
23
|
+
@context.native.enter do
|
24
|
+
yield(self)
|
25
|
+
end if block_given?
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def rb(value)
|
30
|
+
@proxies.js2rb(value) do
|
31
|
+
case value
|
32
|
+
when V8::C::Function then V8::Function.new(value, self)
|
33
|
+
when V8::C::Array then V8::Array.new(value, self)
|
34
|
+
when V8::C::Object then V8::Object.new(value, self)
|
35
|
+
when V8::C::String then value.Utf8Value.tap {|s| return s.respond_to?(:force_encoding) ? s.force_encoding("UTF-8") : s}
|
36
|
+
when V8::C::Date then Time.at(value.NumberValue() / 1000)
|
37
|
+
when V8::C::StackTrace then V8::StackTrace.new(self, value)
|
38
|
+
when V8::C::Value then nil if value.IsEmpty()
|
39
|
+
else
|
40
|
+
value
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def v8(value)
|
46
|
+
case value
|
47
|
+
when V8::Object
|
48
|
+
value.instance_eval {@native}
|
49
|
+
when String
|
50
|
+
C::String::New(value)
|
51
|
+
when Symbol
|
52
|
+
C::String::NewSymbol(value.to_s)
|
53
|
+
when Proc,Method,UnboundMethod
|
54
|
+
@proxies.rb2js(value) do
|
55
|
+
@templates.to_function(value).function
|
56
|
+
end
|
57
|
+
when ::Array
|
58
|
+
C::Array::New(value.length).tap do |a|
|
59
|
+
value.each_with_index do |item, i|
|
60
|
+
a.Set(i, v8(item))
|
61
|
+
end
|
62
|
+
end
|
63
|
+
when ::Hash
|
64
|
+
C::Object::New().tap do |o|
|
65
|
+
value.each do |key, val|
|
66
|
+
o.Set(v8(key), v8(val))
|
67
|
+
end
|
68
|
+
end
|
69
|
+
when ::Time
|
70
|
+
C::Date::New(value.to_f * 1000)
|
71
|
+
when ::Class
|
72
|
+
@proxies.rb2js(value) do
|
73
|
+
constructor = @templates.to_constructor(value)
|
74
|
+
constructor.exposed = true
|
75
|
+
constructor.function
|
76
|
+
end
|
77
|
+
when nil,Numeric,TrueClass,FalseClass, C::Value
|
78
|
+
value
|
79
|
+
else
|
80
|
+
@proxies.rb2js(value) do
|
81
|
+
@templates.to_constructor(value.class).allocate(value)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
|
2
|
+
module V8
|
3
|
+
class Portal
|
4
|
+
class Caller
|
5
|
+
|
6
|
+
def initialize(portal)
|
7
|
+
@portal = portal
|
8
|
+
end
|
9
|
+
|
10
|
+
def raw
|
11
|
+
yield
|
12
|
+
rescue Exception => e
|
13
|
+
case e
|
14
|
+
when SystemExit, NoMemoryError
|
15
|
+
raise e
|
16
|
+
else
|
17
|
+
error = V8::C::Exception::Error(V8::C::String::New(e.message))
|
18
|
+
#TODO: This is almost certainly a crash here.
|
19
|
+
#we need to hold onto `error` while it bubbles up the javascript stack.
|
20
|
+
error.SetHiddenValue("TheRubyRacer::Cause", C::External::New(e))
|
21
|
+
V8::C::ThrowException(error)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def protect(*args, &block)
|
26
|
+
@portal.v8 raw(*args, &block)
|
27
|
+
end
|
28
|
+
|
29
|
+
def invoke(code, *args, &block)
|
30
|
+
protect do
|
31
|
+
args = args.slice(0, code.arity) if code.arity >= 0
|
32
|
+
code.call(*args, &block)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
|
2
|
+
module V8
|
3
|
+
class Portal
|
4
|
+
class ConstructorAdapter
|
5
|
+
attr_reader :template, :exposed
|
6
|
+
alias_method :exposed?, :exposed
|
7
|
+
|
8
|
+
def initialize(templates, class_id)
|
9
|
+
@exposed = false
|
10
|
+
@class_id = class_id
|
11
|
+
@templates = templates
|
12
|
+
@invoke = method(:invoke)
|
13
|
+
@template = C::FunctionTemplate::New(@invoke)
|
14
|
+
portal.interceptors.setup(@template.InstanceTemplate())
|
15
|
+
cls = self.ruby_class
|
16
|
+
superclass = cls.superclass
|
17
|
+
if cls != ::Object && superclass != ::Object && superclass != ::Class
|
18
|
+
@template.Inherit(templates.to_constructor(superclass).template)
|
19
|
+
end
|
20
|
+
if cls.name && cls.name =~ /(::)?(\w+?)$/
|
21
|
+
template.SetClassName(C::String::NewSymbol("rb::" + $2))
|
22
|
+
else
|
23
|
+
template.SetClassName("Ruby")
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def function
|
28
|
+
@template.GetFunction()
|
29
|
+
end
|
30
|
+
|
31
|
+
def allocate(object)
|
32
|
+
arguments = C::Array::New(1)
|
33
|
+
arguments.Set(0, C::External::New(object))
|
34
|
+
function.NewInstance(arguments)
|
35
|
+
end
|
36
|
+
|
37
|
+
def disable
|
38
|
+
@disabled = true
|
39
|
+
end
|
40
|
+
|
41
|
+
def enable
|
42
|
+
@disabled = nil
|
43
|
+
end
|
44
|
+
|
45
|
+
def invoke(arguments)
|
46
|
+
return if @disabled
|
47
|
+
if !@exposed
|
48
|
+
unless arguments.Length() == 1 && arguments[0].kind_of?(C::External)
|
49
|
+
C::ThrowException(C::Exception::Error(C::String::New("cannot call native constructor from javascript")))
|
50
|
+
else
|
51
|
+
object = arguments[0].Value()
|
52
|
+
proxies.register_javascript_proxy arguments.This(), :for => object
|
53
|
+
end
|
54
|
+
else
|
55
|
+
instance = nil
|
56
|
+
if arguments.Length() > 0 && arguments[0].kind_of?(C::External)
|
57
|
+
instance = arguments[0].Value()
|
58
|
+
else
|
59
|
+
rbargs = []
|
60
|
+
for i in 0..arguments.Length() - 1
|
61
|
+
rbargs << @templates.portal.rb(arguments[i])
|
62
|
+
end
|
63
|
+
instance = portal.caller.raw do
|
64
|
+
self.ruby_class.new(*rbargs)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
proxies.register_javascript_proxy arguments.This(), :for => instance
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def exposed=(exposed)
|
72
|
+
if exposed && !@augmented
|
73
|
+
#create a prototype so that this constructor also acts like a ruby object
|
74
|
+
prototype_template = C::ObjectTemplate::New()
|
75
|
+
portal.interceptors.setup(prototype_template)
|
76
|
+
prototype = prototype_template.NewInstance()
|
77
|
+
#set *that* object's prototype to an empty function so that it will look and behave like a function.
|
78
|
+
prototype.SetPrototype(C::FunctionTemplate::New().GetFunction())
|
79
|
+
template.GetFunction().SetPrototype(prototype)
|
80
|
+
@augmented = true
|
81
|
+
end
|
82
|
+
@exposed = exposed
|
83
|
+
end
|
84
|
+
|
85
|
+
def ruby_class
|
86
|
+
ObjectSpace._id2ref(@class_id)
|
87
|
+
end
|
88
|
+
|
89
|
+
def proxies
|
90
|
+
@templates.proxies
|
91
|
+
end
|
92
|
+
|
93
|
+
def portal
|
94
|
+
@templates.portal
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module V8
|
2
|
+
class Portal
|
3
|
+
class FunctionAdapter
|
4
|
+
|
5
|
+
attr_reader :template
|
6
|
+
|
7
|
+
def initialize(portal, code)
|
8
|
+
@portal = portal
|
9
|
+
@caller = case code
|
10
|
+
when Method then BoundCall.new(portal)
|
11
|
+
when UnboundMethod then BindAndCall.new(portal)
|
12
|
+
else Call.new(portal)
|
13
|
+
end
|
14
|
+
@code = code
|
15
|
+
@template = V8::C::FunctionTemplate::New(@caller, @code)
|
16
|
+
end
|
17
|
+
|
18
|
+
def function
|
19
|
+
@template.GetFunction()
|
20
|
+
end
|
21
|
+
|
22
|
+
class Call
|
23
|
+
def initialize(portal)
|
24
|
+
@portal = portal
|
25
|
+
end
|
26
|
+
|
27
|
+
def call(arguments)
|
28
|
+
proc = arguments.Data()
|
29
|
+
rbargs = [@portal.rb(arguments.This())]
|
30
|
+
for i in 0..arguments.Length() - 1
|
31
|
+
rbargs << @portal.rb(arguments[i])
|
32
|
+
end
|
33
|
+
@portal.caller.invoke(proc, *rbargs)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class BoundCall < Call
|
38
|
+
def call(arguments)
|
39
|
+
proc = arguments.Data()
|
40
|
+
rbargs = []
|
41
|
+
for i in 0..arguments.Length() - 1
|
42
|
+
rbargs << @portal.rb(arguments[i])
|
43
|
+
end
|
44
|
+
@portal.caller.invoke(proc, *rbargs)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
class BindAndCall < Call
|
49
|
+
def call(arguments)
|
50
|
+
method = arguments.Data()
|
51
|
+
rbargs = []
|
52
|
+
for i in 0..arguments.Length() - 1
|
53
|
+
rbargs << @portal.rb(arguments[i])
|
54
|
+
end
|
55
|
+
this = @portal.rb(arguments.This())
|
56
|
+
@portal.caller.protect do
|
57
|
+
method.bind(this).call(*rbargs)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,152 @@
|
|
1
|
+
module V8
|
2
|
+
class Portal
|
3
|
+
class Interceptors
|
4
|
+
def initialize(portal)
|
5
|
+
@getter = NamedPropertyGetter.new(portal)
|
6
|
+
@setter = NamedPropertySetter.new(portal)
|
7
|
+
@query = nil
|
8
|
+
@deleter = nil
|
9
|
+
@enumerator = NamedPropertyEnumerator.new(portal)
|
10
|
+
@igetter = IndexedPropertyGetter.new(portal)
|
11
|
+
@isetter = IndexedPropertySetter.new(portal)
|
12
|
+
@iquery = nil
|
13
|
+
@ideleter = nil
|
14
|
+
@ienumerator = IndexedPropertyEnumerator.new(portal)
|
15
|
+
end
|
16
|
+
|
17
|
+
def setup(template)
|
18
|
+
template.SetNamedPropertyHandler(@getter,@setter,@query,@deleter,@enumerator, nil)
|
19
|
+
template.SetIndexedPropertyHandler(@igetter,@isetter,@iquery,@ideleter,@ienumerator, nil)
|
20
|
+
end
|
21
|
+
|
22
|
+
class PropertyAttributes
|
23
|
+
attr_reader :flags
|
24
|
+
def initialize
|
25
|
+
@flags = 0
|
26
|
+
end
|
27
|
+
|
28
|
+
def read_only
|
29
|
+
tap do
|
30
|
+
@flags |= V8::C::ReadOnly
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def dont_enum
|
35
|
+
tap do
|
36
|
+
@flags |= V8::C::DontEnum
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def dont_delete
|
41
|
+
tap do
|
42
|
+
@flags |= V8::C::DontDelete
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
class Interceptor
|
48
|
+
|
49
|
+
def initialize(portal)
|
50
|
+
@to, @access = portal, portal.access
|
51
|
+
end
|
52
|
+
|
53
|
+
def intercept(info, retval = nil, &code)
|
54
|
+
obj = @to.rb(info.This())
|
55
|
+
intercepts = true
|
56
|
+
result = @to.caller.protect do
|
57
|
+
dontintercept = proc do
|
58
|
+
intercepts = false
|
59
|
+
end
|
60
|
+
code.call(obj, dontintercept)
|
61
|
+
end
|
62
|
+
intercepts ? (retval || result) : C::Empty
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
class NamedPropertyGetter < Interceptor
|
67
|
+
def call(property, info)
|
68
|
+
intercept(info) do |obj, dontintercept|
|
69
|
+
@access.get(obj, @to.rb(property), &dontintercept)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
class NamedPropertySetter < Interceptor
|
75
|
+
def call(property, value, info)
|
76
|
+
intercept(info, value) do |obj, dontintercept|
|
77
|
+
@access.set(obj, @to.rb(property), @to.rb(value), &dontintercept)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
class NamedPropertyQuery
|
83
|
+
def call(property, info)
|
84
|
+
attributes = PropertyAttributes.new
|
85
|
+
result = intercept(info) do |obj, dontintercept|
|
86
|
+
@access.query(obj, @to.rb(property), attributes, &dontintercept)
|
87
|
+
end
|
88
|
+
return result == C::Empty ? result : C::Integer::New(attributes.flags)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
class NamedPropertyEnumerator < Interceptor
|
93
|
+
def call(info)
|
94
|
+
intercept(info) do |obj, dontintercept|
|
95
|
+
@access.names(obj, &dontintercept).to_a
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
class NamedPropertyDeleter < Interceptor
|
101
|
+
def call(property, info)
|
102
|
+
intercept(info) do |obj, dontintercept|
|
103
|
+
@access.delete(obj, property, &dontintercept)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
class IndexedPropertyGetter < Interceptor
|
109
|
+
def call(index, info)
|
110
|
+
intercept(info) do |obj, dontintercept|
|
111
|
+
@access.iget(obj, index, &dontintercept)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
class IndexedPropertySetter < Interceptor
|
117
|
+
def call(index, value, info)
|
118
|
+
intercept(info, value) do |obj, dontintercept|
|
119
|
+
@access.iset(obj, index, @to.rb(value), &dontintercept)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
class IndexedPropertyQuery < Interceptor
|
125
|
+
def call(property, info)
|
126
|
+
attributes = PropertyAttributes.new
|
127
|
+
result = intercept(info) do |obj, dontintercept|
|
128
|
+
@access.indices(obj, &dontintercept)
|
129
|
+
end
|
130
|
+
result == C::Empty ? C::Empty : C::Integer::New(attributes.flags)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
class IndexedPropertyDeleter < Interceptor
|
135
|
+
def call(index, info)
|
136
|
+
intercept(info) do |obj, dontintercept|
|
137
|
+
@access.idelete(obj, index, &dontintercept)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
class IndexedPropertyEnumerator < Interceptor
|
143
|
+
def call(info)
|
144
|
+
intercept(info) do |obj, dontintercept|
|
145
|
+
@access.indices(obj, &dontintercept)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|